doufei1852 2017-08-09 22:10
浏览 88
已采纳

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

The following function lives in the folder 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
}

it's meant to output the execution time of the opcode opAdd in the execution of the Ethereum virtual machine, which looks like this:

enter image description here

However, what I'd like to do is have this information only display when it's running a programme that I've initiated locally, on my own network node.

Here is a function in the file 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
}

This function only executes when one submits a transaction to the network, and outputs Submitted transaction in the terminal window's console.

Is there a way that I could pass a boolean flag from go-ethereum/internal/ethapi/api.go to go-ethereum/core/vm/instructions.go, right before it outputs Submitted transaction so that I could execute the opcode execution time catalouging functionality?


EDIT

enter image description here

From the file 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
}

and from 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条回答 默认 最新

  • douduiwei2831 2017-08-09 23:05
    关注

    To control whether timing information is output in instructions.go, yes you could add a boolean variable to the file instructions.go (perhaps something like):

    var Debug bool
    

    and wrap the logging in a check on it:

    if Debug {
       // log ellapsed execution time
    fmt.Println("execute opAdd consume = ",(time.Now().UnixNano() - startTime))
    }
    

    and then set it somewhere (for example in your api pkg) with

    import ".../core/vm"
    vm.Debug = true 
    

    this is not goroutine safe so would have to be set once on startup depending on conditions or protected with a mutex. It's also pretty horrible but as a quick hack to see it work you could do this (sorry not familiar with this particular code base) .

    I'm not clear on how opAdd is triggered by your other code if it was directly called you could of course just add a parameter to the function to control the output from the calling site, this would be preferable.

    Normally this sort of thing you'd either:

    1. Pass in whether to debug or not to the function call opAdd
    2. Set a global debugging level on startup once to control whether logging takes place or at what level globally and this would affect all such tracing.

    They do have a log package, I don't know why it's not used here:

    https://github.com/ethereum/go-ethereum/blob/master/log/logger.go

    EDIT

    I would just always allocate startTime , but if you wish to avoid that, you need to declare it at the top level, compare this to your code above:

    // wrap the logging in a check
    var startTime time.Time
    if OpcodeTrigger {
        // begin execution time tracking
        startTime = time.Now().UnixNano();
    }
    

    NB if this is concurrent at all you should be adding a mutex to the vm pkg and only mutating OpCodeTrigger with a function which wraps the access with a mu.Lock - at that point you might start to ask yourself if there are better ways to do this :)

    Better if you get stuck again to ask on a forum like forum.golangbridge.org as stackoverflow is not designed for extensive back and forth.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 远程桌面文档内容复制粘贴,格式会变化
  • ¥15 关于#java#的问题:找一份能快速看完mooc视频的代码
  • ¥15 这种微信登录授权 谁可以做啊
  • ¥15 请问我该如何添加自己的数据去运行蚁群算法代码
  • ¥20 用HslCommunication 连接欧姆龙 plc有时会连接失败。报异常为“未知错误”
  • ¥15 网络设备配置与管理这个该怎么弄
  • ¥20 机器学习能否像多层线性模型一样处理嵌套数据
  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题