Golang:从 file/sub-directory A 中的函数传递布尔标志到 file/sub-directory B 中的函数
Golang: pass boolean flag from function in file/sub-directory A, to function in file/sub-directory B
以下函数位于文件夹 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
}
此函数仅在向网络提交交易时执行,并在终端 window 的控制台中输出 Submitted transaction
。
有没有一种方法可以在输出 Submitted transaction
之前将布尔标志从 go-ethereum/internal/ethapi/api.go
传递到 go-ethereum/core/vm/instructions.go
,以便我可以执行操作码执行时间编目功能?
编辑
来自文件 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
}
要控制是否在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,您当然可以只向函数添加一个参数来控制调用站点的输出,这样更好。
通常这种事情你会:
- 给函数调用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 这样的论坛上提问,因为 Whosebug 不是为广泛的来回设计的。
以下函数位于文件夹 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
}
此函数仅在向网络提交交易时执行,并在终端 window 的控制台中输出 Submitted transaction
。
有没有一种方法可以在输出 Submitted transaction
之前将布尔标志从 go-ethereum/internal/ethapi/api.go
传递到 go-ethereum/core/vm/instructions.go
,以便我可以执行操作码执行时间编目功能?
编辑
来自文件 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
}
要控制是否在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,您当然可以只向函数添加一个参数来控制调用站点的输出,这样更好。
通常这种事情你会:
- 给函数调用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 这样的论坛上提问,因为 Whosebug 不是为广泛的来回设计的。