Golang:从文件/子目录A中的函数传递布尔标志到文件/子目录B

时间:2017-08-09 22:10:20

标签: go architecture boolean flags

以下函数位于文件夹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的执行时间,如下所示:

enter image description here

但是,我想要做的是,只有当我在我自己的网络节点上运行我在本地启动的程序时,才会显示此信息。

以下是文件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功能?

修改

enter image description here

来自档案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
}

1 个答案:

答案 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,你当然可以在函数中添加一个参数来控制调用站点的输出,这样会更好。

通常你会这样做:

  1. 传入是否调试函数调用opAdd
  2. 在启动时设置一次全局调试级别,以控制是否发生日志记录或全局级别,这将影响所有此类跟踪。
  3. 他们有一个日志包,我不知道为什么它没有在这里使用:

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