以下函数位于文件夹go-ethereum/core/vm/instructions.go
:
func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
// begin execution time tracking
var startTime = time.Now().UnixNano();
x, y := stack.pop(), stack.pop()
stack.push(math.U256(x.Add(x, y)))
evm.interpreter.intPool.put(y)
// log ellapsed execution time
fmt.Println("execute opAdd consume = ",(time.Now().UnixNano() - startTime))
return nil, nil
}
它意味着在执行以太坊虚拟机时输出操作码opAdd
的执行时间,如下所示:
但是,我想要做的是,只有当我在我自己的网络节点上运行我在本地启动的程序时,才会显示此信息。
以下是文件go-ethereum/internal/ethapi/api.go
中的一个函数:
// SendRawTransaction will add the signed transaction to the transaction pool.
// The sender is responsible for signing the transaction and using the correct nonce.
func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encodedTx hexutil.Bytes) (string, error) {
tx := new(types.Transaction)
if err := rlp.DecodeBytes(encodedTx, tx); err != nil {
return "", err
}
if err := s.b.SendTx(ctx, tx); err != nil {
return "", err
}
signer := types.MakeSigner(s.b.ChainConfig(), s.b.CurrentBlock().Number())
if tx.To() == nil {
from, err := types.Sender(signer, tx)
if err != nil {
return "", err
}
addr := crypto.CreateAddress(from, tx.Nonce())
log.Info("Submitted contract creation", "fullhash", tx.Hash().Hex(), "contract", addr.Hex())
} else {
log.Info("Submitted transaction", "fullhash", tx.Hash().Hex(), "recipient", tx.To())
}
return tx.Hash().Hex(), nil
}
此功能仅在向网络提交交易时执行,并在终端窗口的控制台中输出Submitted transaction
。
有没有一种方法可以将go-ethereum/internal/ethapi/api.go
的布尔标志传递给go-ethereum/core/vm/instructions.go
,就在它输出Submitted transaction
之前,以便我可以执行操作码执行时间catalouging功能?
修改
来自档案go-ethereum/internal/ethapi/api.go
:
// submitTransaction is a helper function that submits tx to txPool and logs a message.
func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (common.Hash, error) {
if err := b.SendTx(ctx, tx); err != nil {
return common.Hash{}, err
}
if tx.To() == nil {
signer := types.MakeSigner(b.ChainConfig(), b.CurrentBlock().Number())
from, _ := types.Sender(signer, tx)
addr := crypto.CreateAddress(from, tx.Nonce())
log.Info("Submitted contract creation", "fullhash", tx.Hash().Hex(), "contract", addr.Hex())
} else {
// flag for opcode execution time tracking
vm.OpcodeTrigger = true
log.Info("Submitted transaction", "fullhash", tx.Hash().Hex(), "recipient", tx.To())
}
return tx.Hash(), nil
}
和go-ethereum/core/vm/instructions.go
:
var (
OpcodeTrigger bool
bigZero = new(big.Int)
)
func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
// wrap the logging in a check
if OpcodeTrigger {
// begin execution time tracking
var startTime = time.Now().UnixNano();
}
x, y := stack.pop(), stack.pop()
stack.push(math.U256(x.Add(x, y)))
evm.interpreter.intPool.put(y)
// wrap the logging in a check
if OpcodeTrigger {
// now set the boolean flag back to false
OpcodeTrigger = false
// log ellapsed execution time
fmt.Println("execute opAdd consume = ",(time.Now().UnixNano() - startTime))
}
return nil, nil
}
答案 0 :(得分:2)
要控制是否在instructions.go中输出定时信息,是的,你可以在文件instructions.go中添加一个布尔变量(也许是这样的):
var Debug bool
并将日志记录包装在其中:
if Debug {
// log ellapsed execution time
fmt.Println("execute opAdd consume = ",(time.Now().UnixNano() - startTime))
}
然后使用
将其设置在某处(例如在您的api pkg中)import ".../core/vm"
vm.Debug = true
这不是goroutine安全的,因此必须在启动时设置一次,具体取决于条件或使用互斥锁保护。它也非常可怕,但作为一个快速的黑客看到它的工作,你可以这样做(抱歉不熟悉这个特定的代码库)。
我不清楚你的其他代码如何直接调用opAdd,你当然可以在函数中添加一个参数来控制调用站点的输出,这样会更好。
通常你会这样做:
他们有一个日志包,我不知道为什么它没有在这里使用:
https://github.com/ethereum/go-ethereum/blob/master/log/logger.go
编辑
我总是会分配startTime,但是如果你想避免这种情况,你需要在顶层声明它,将它与上面的代码进行比较:
// wrap the logging in a check
var startTime time.Time
if OpcodeTrigger {
// begin execution time tracking
startTime = time.Now().UnixNano();
}
请注意,如果这是并发的,你应该在vm pkg中添加一个互斥锁,并且只使用一个用mu.Lock封装访问权限的函数来改变OpCodeTrigger - 此时你可能会开始问自己是否有更好的方法这样做:))
如果你再次被问到像forum.golangbridge.org这样的论坛,那就更好了,因为stackoverflow不是为来回广泛而设计的。