目录
现在自己对其中一些代码的理解还不够,等我逐渐深入学习后回回来再修改的。
其中对于一些代码的理解参考了以太坊黄皮书的内容。
链接: https://ethereum.github.io/yellowpaper/paper.pdf
| 类型名 | 位置 | 定义 |
|---|---|---|
| Hash | common/types.go | 32byte |
| Address | common/types.go | 20byte |
| Bloom | core/types/bloom9.go | 256byte(filter) |
| GasPool | core/gaspool.go | uint64 |
位于core\types\receipt.go
为了方便索引、搜索交易和对交易的零知识证明,将交易执行中的某些信息进行编码形成了Receipt

参考黄皮书4.3.1
| 名字 | 定义 |
|---|---|
| Type | 交易类型 |
| PostState | StateDB的MPT树根,相当于当前Block事务执行后所有账户状态 |
| Status | 当前交易的状态 |
| CumulativeGasUsed | 累积的Gas使用量 |
| Bloom | 布隆过滤器,用来快速验证给定Log是否为这个事务生成 |
| Logs | 交易执行过程中生成的log集合 |
| TxHash | 交易hash值 |
| ContractAddress | 交易对应智能合约地址 |
| GasUsed | 使用的Gas量 |
| BlockHash | 区块hash |
| BlockNumber | 区块号 |
| TransactionIndex | 交易索引 |
位于core\types\log.go
以太坊中定义了event和log机制,用于表示一个合约的日志。

| 名字 | 定义 |
|---|---|
| Address | 对应事件的合约地址 |
| Topics | 用于检索日志时使用 |
| Data | 由合约提供的ABI编码的内容 |
| BlockNumber | 区块号 |
| TxHash | 交易hash |
| TxIndex | 该Log对应的交易在区块中的索引 |
| BlockHash | 该Log对应的交易所在的区块hash |
| Index | 该Log在区块中的索引 |
| Removed | 当发生了链重组导致log被恢复,该字段为真。故如果通过过滤器查询log时,要多注意该字段。 |

位于core\types\block.go
表示区块头
| 名字 | 定义 |
|---|---|
| ParentHash | 父区块的hash值 |
| UncleHash | 叔区块RLP编码hash |
| Coinbase | 矿工地址 |
| Root | 世界状态的根hash |
| TxHash | 交易信息的根hash |
| ReceiptHash | 收据信息的根hash |
| Bloom | 布隆过滤器 |
| Difficulty | 挖矿的难度系数 |
| Number | 区块序号 |
| GasLimit | 区块内Gas消耗上限 |
| GasUsed | 区块交易完成后消耗Gas总量 |
| Time | 区块生成的时间(貌似并不太精准) |
| Extra | 区块创建者(矿工)记录的信息 |
| MixDigest | hashimotoFull函数生成后的digest生成的hash值,可用于结合nonce进行工作量证明 |
| Nonce | Pow枚举猜测的值 |
| BaseFee | EIP-1559新增的区块头可选项,允许协议强制执行最低费用,而不会激励矿工和交易方在链下交易,形成链外市场。 |
位于params\config.go
代表区块链的配置

| 名字 | 定义 |
|---|---|
| DAOForkBlock | DAO硬分叉的区块号 |
| DAOForkSupport | 当前节点是否支持DAO硬分叉 |

位于core\blockchain.go
待补充


位于core\types\transaction.go
其中txdata是一个接口,定义如下,位于相同位置

位于core\types\transaction.go
| 名字 | 定义 |
|---|---|
| inner | 交易相关共识内容 |
| time | 交易时间 |
| hash | 交易hash值 |
| size | 交易大小 |
| from | 交易发起方 |

位于core\types\block.go
表示区块
| 名字 | 定义 |
|---|---|
| ParentHash | 父区块的hash值 |
| UncleHash | 叔区块RLP编码hash |
| Coinbase | 矿工地址 |
| Root | 世界状态的根hash |
| TxHash | 交易信息的根hash |
| ReceiptHash | 收据信息的根hash |
| Bloom | 布隆过滤器 |
| Difficulty | 挖矿的难度系数 |

位于core\state_processor.go
| 名字 | 定义 |
|---|---|
| config | 区块配置 |
| bc | 区块链 |
| engine | 用于区块奖励的共识引擎 |
位于core\vm\evm.go
表示区块上下文,很多属性和前面是重复的。

| 名字 | 定义 |
|---|---|
| CoinBase | 矿工地址 |
| GasLimit | Gas的限制量 |
| BlockNumber | 区块号 |
| Time | 时间 |
| Difficulty | 难度 |
| BaseFee | 协议执行最低费用 |
位于core\vm\evm.go
待补充

| 名字 | 定义 |
|---|---|
| interpreter | 解释编译程序 |

位于core\types\transaction.go
派生的事务(待补充)
| 名字 | 定义 |
|---|---|
| nonce | 即为交易中的nonce,用来交易排序,交易校验以避免双花 |
| gasLimit | 当前消息gas最大限制 |
| gasPrice | 油价 |
| gasFeeCap | 用户所能支付给矿工的最大单价限额 |
| gasTipCap | 小费,即在网络拥堵的情况下支付给矿工的小费,这个也意味着矿工有优先选择权。支付该费用,则优先打包区块 |

位于core\state\statedb.go
StateDB结构用于存储所有的与Merkle trie相关的存储, 包括一些循环state结构

位于core\state\access_list.go
每个事务的访问列表,在某些形式的 EVM 执行过程中会触及的账户和合约存储位置的列表

位于consensus\consensus.go
engine是一个算法无关的用作共识层面的引擎
位于core\state_processor.go
func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) {
var (
receipts types.Receipts
usedGas = new(uint64)
header = block.Header()
blockHash = block.Hash()
blockNumber = block.Number()
allLogs []*types.Log
gp = new(GasPool).AddGas(block.GasLimit())
)
// Mutate the block and state according to any hard-fork specs
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
misc.ApplyDAOHardFork(statedb)
}
blockContext := NewEVMBlockContext(header, p.bc, nil)
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg)
// Iterate over and process the individual transactions
for i, tx := range block.Transactions() {
msg, err := tx.AsMessage(types.MakeSigner(p.config, header.Number), header.BaseFee)
if err != nil {
return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
}
statedb.Prepare(tx.Hash(), i)
receipt, err := applyTransaction(msg, p.config, p.bc, nil, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv)
if err != nil {
return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
}
receipts = append(receipts, receipt)
allLogs = append(allLogs, receipt.Logs...)
}
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles())
return receipts, allLogs, *usedGas, nil
}
首先该函数判断当前区块是否为DAO硬分叉的区块,若是则调用ApplyDAOHardFork函数(待补充)。
然后调用NewEVMBlockContext函数为当前区块创立一个运行上下文。
随后调用NewEVM函数建立一个以太坊虚拟机,准备编译执行程序。
然后枚举区块中的交易并把它转换为消息格式,随后调用Prepare函数设置当前状态的交易hash和序号,随后调用applyTransaction在虚拟机中执行交易相关指令(见以太坊go-ethereum源码研读(二)进一步分析),得到返回的收据后,加入到列表中,并获取其中的日志加入到列表中,最后调用共识引擎的Finalize函数计算区块奖励并加入到最终状态中。
位于core\evm.go
根据区块头信息,建立并返回一个BlockContext区块上下文信息结构体
func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common.Address) vm.BlockContext {
var (
beneficiary common.Address
baseFee *big.Int
)
// If we don't have an explicit author (i.e. not mining), extract from the header
if author == nil {
beneficiary, _ = chain.Engine().Author(header) // Ignore error, we're past header validation
} else {
beneficiary = *author
}
if header.BaseFee != nil {
baseFee = new(big.Int).Set(header.BaseFee)
}
return vm.BlockContext{
CanTransfer: CanTransfer,
Transfer: Transfer,
GetHash: GetHashFn(header, chain),
Coinbase: beneficiary,
BlockNumber: new(big.Int).Set(header.Number),
Time: new(big.Int).SetUint64(header.Time),
Difficulty: new(big.Int).Set(header.Difficulty),
BaseFee: baseFee,
GasLimit: header.GasLimit,
}
}
位于core/vm/evm.go
根据之前的上下文信息,以及其他的配置和内容建立虚拟机,同时调用NewEVMInterpreter函数建立对应解释器。
// NewEVM returns a new EVM. The returned EVM is not thread safe and should
// only ever be used *once*.
func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config) *EVM {
evm := &EVM{
Context: blockCtx,
TxContext: txCtx,
StateDB: statedb,
Config: config,
chainConfig: chainConfig,
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil),
}
evm.interpreter = NewEVMInterpreter(evm, config)
return evm
}
根据采取的不同链规则不同来建立对应EVM解释器
// NewEVMInterpreter returns a new instance of the Interpreter.
func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
// If jump table was not initialised we set the default one.
if cfg.JumpTable == nil {
switch {
case evm.chainRules.IsLondon:
cfg.JumpTable = &londonInstructionSet
case evm.chainRules.IsBerlin:
cfg.JumpTable = &berlinInstructionSet
case evm.chainRules.IsIstanbul:
cfg.JumpTable = &istanbulInstructionSet
case evm.chainRules.IsConstantinople:
cfg.JumpTable = &constantinopleInstructionSet
case evm.chainRules.IsByzantium:
cfg.JumpTable = &byzantiumInstructionSet
case evm.chainRules.IsEIP158:
cfg.JumpTable = &spuriousDragonInstructionSet
case evm.chainRules.IsEIP150:
cfg.JumpTable = &tangerineWhistleInstructionSet
case evm.chainRules.IsHomestead:
cfg.JumpTable = &homesteadInstructionSet
default:
cfg.JumpTable = &frontierInstructionSet
}
for i, eip := range cfg.ExtraEips {
copy := *cfg.JumpTable
if err := EnableEIP(eip, ©); err != nil {
// Disable it, so caller can check if it's activated or not
cfg.ExtraEips = append(cfg.ExtraEips[:i], cfg.ExtraEips[i+1:]...)
log.Error("EIP activation failed", "eip", eip, "error", err)
}
cfg.JumpTable = ©
}
}
return &EVMInterpreter{
evm: evm,
cfg: cfg,
}
}
位于core\types\transaction.go
将交易返回为消息格式
// AsMessage returns the transaction as a core.Message.
func (tx *Transaction) AsMessage(s Signer, baseFee *big.Int) (Message, error) {
msg := Message{
nonce: tx.Nonce(),
gasLimit: tx.Gas(),
gasPrice: new(big.Int).Set(tx.GasPrice()),
gasFeeCap: new(big.Int).Set(tx.GasFeeCap()),
gasTipCap: new(big.Int).Set(tx.GasTipCap()),
to: tx.To(),
amount: tx.Value(),
data: tx.Data(),
accessList: tx.AccessList(),
isFake: false,
}
// If baseFee provided, set gasPrice to effectiveGasPrice.
if baseFee != nil {
msg.gasPrice = math.BigMin(msg.gasPrice.Add(msg.gasTipCap, baseFee), msg.gasFeeCap)
}
var err error
msg.from, err = Sender(s, tx)
return msg, err
}
位于core\state\statedb.go
在EVM需要生成新的状态时调用此函数来设置当前交易的hash和序号
// Prepare sets the current transaction hash and index which are
// used when the EVM emits new state logs.
func (s *StateDB) Prepare(thash common.Hash, ti int) {
s.thash = thash
s.txIndex = ti
s.accessList = newAccessList()
}
// Finalize implements consensus.Engine, accumulating the block and uncle rewards,
// setting the final state on the header
func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) {
// Accumulate any block and uncle rewards and commit the final state root
accumulateRewards(chain.Config(), state, header, uncles)
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
}
位于consensus\ethash\consensus.go
该函数累积区块和叔块的奖励并设置在头部的最终状态中。
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最
我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些
有这些railscast。http://railscasts.com/episodes/218-making-generators-in-rails-3有了这个,你就会知道如何创建样式表和脚手架生成器。http://railscasts.com/episodes/216-generators-in-rails-3通过这个,您可以了解如何添加一些文件来修改脚手架View。我想把两者结合起来。我想创建一个生成器,它也可以创建脚手架View。有点像RyanBates漂亮的生成器或web_app_themegem(https://github.com/pilu/web-app-theme)。我
是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s
我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty
如何使此根路径转到:“/dashboard”而不仅仅是http://example.com?root:to=>'dashboard#index',:constraints=>lambda{|req|!req.session[:user_id].blank?} 最佳答案 您可以通过以下方式实现:root:to=>redirect('/dashboard')match'/dashboard',:to=>"dashboard#index",:constraints=>lambda{|req|!req.session[:user_id].b
Heroku支持人员告诉我,为了在我的Web应用程序中使用自定义字体(未安装在系统中,您可以在bash控制台中使用fc-list查看已安装的字体)我必须部署一个包含所有字体的.fonts文件夹里面的字体。问题是我不知道该怎么做。我的意思是,我不知道文件名是否必须遵循heroku的任何特殊模式,或者我必须在我的代码中做一些事情来考虑这种字体,或者如果我将它包含在文件夹中它是自动的......事实是,我尝试以不同的方式更改字体的文件名,但根本没有使用该字体。为了提供更多详细信息,我们使用字体的过程是将PDF转换为图像,更具体地说,使用rghostgem。并且最终图像根本不使用自定义字体。在
您将如何构建一个简单的Sinatra应用程序?我正在制作,我希望该应用具有以下功能:“应用程序”更像是一个包含所有信息的管理仪表板。然后另一个应用程序将通过REST访问信息。我还没有创建仪表板,只是从数据库中获取东西session和身份验证(尚未实现)您可以上传图片,其他应用可以显示这些图片我已经使用RSpec创建了一个测试文件通过Prawn生成报告目前的设置是这样的:app.rbtest_app.rb因为我实际上只有应用程序和测试文件。到目前为止,我已经将Datamapper用于ORM,将SQLite用于数据库。这是我的第一个Ruby/Sinatra项目,所以欢迎任何和所有建议-我应