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,您当然可以只向函数添加一个参数来控制调用站点的输出,这样更好。

通常这种事情你会:

  1. 给函数调用opAdd传入是否调试
  2. 在启动时设置一个全局调试级别一次,以控制是否进行日志记录或在什么级别全局进行日志记录,这将影响所有此类跟踪。

他们有日志包,不知道为什么这里没有用:

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 不是为广泛的来回设计的。