фильтр для ограничения вывода данных кода операции только контрактами/функциями, вызываемыми локальным узлом

Изменив файл commands.gogeth , я смог увидеть время выполнения отдельных опкодов, оно выглядит так:

введите описание изображения здесь

Моя интерпретация этого вывода заключается в том, что он представляет собой выполнение всех контрактов, о которых слышит мой работающий узел, а значит, и всех транзакций всей сети (ropsten testnet).

Изменения, которые я внес в gethклиент, находятся здесь:

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
}

Что я хотел бы сделать, так это каким-то образом ограничить этот вывод, чтобы он отображался только для контрактов/функций, которые я развертываю с моего локального узла, то есть тех, которые я вызываю сам.

То, что я ищу сейчас, это некоторые мысли о том, как это сделать - даже не обязательно решение - хотя это было бы здорово - но даже места для начала - например, некоторый код, который соответствует своего рода фильтру/флагу, все такие вещи, все эти идеи были бы очень крутыми и полезными!

Ответы (2)

Я снова и снова читаю источник вызова vm, но не могу найти правильный способ вычисления времени выполнения одной функции (иногда один вызов другого). когда мы развернем контракт, это создаст транзакцию, inputатрибутом является байт-код контракта, если мы вызываем метод, сначала генерируем подпись метода (например: 0xe079bdf1), затем находим этот метод по подписи и выполняем. Таким образом, единственный способ получить ответ - код операции vm, и я прочитал сборку Solidity и протестировал множество вызовов методов, проанализировал множество кодов операций, но не могу найти ответ, это так сложно для меня. объявление кодов операций следует:

.data
  0:
    .code
      PUSH 60           contract Wallet {\n
    mappin...
      PUSH 40           contract Wallet {\n
    mappin...
      MSTORE            contract Wallet {\n
    mappin...
      PUSH 0            contract Wallet {\n
    mappin...
      CALLDATALOAD          contract Wallet {\n
    mappin...
      PUSH 100000000000000000000000000000000000000000000000000000000            contract Wallet {\n
    mappin...
      SWAP1             contract Wallet {\n
    mappin...
      DIV           contract Wallet {\n
    mappin...
      PUSH FFFFFFFF         contract Wallet {\n
    mappin...
      AND 

      ......

Может быть, ответа нет, может быть, мой метод анализа неверен. Если кто-то знает правильный ответ, подскажите. Надеюсь поможет~

чувак, что ты думаешь об этой идее
проверьте это - я поставил свое решение в качестве ответа - что вы думаете?

ладно, это своего рода хак, но... кажется, я понял. Вот как это происходит:

Я понял, что всякий раз, когда мы вызываем контракт локально, что я и пытаюсь отследить, мы слышим об этом в консоли в виде, например "Submitted transaction":

введите описание изображения здесь

Что я сделал, так это поместил логический флаг в функцию, которая вызывает этот "Submitted transaction"текст, это логическое значение является, так сказать, « точкой входа / шлюзом » для оболочки кода отслеживания времени.

Вот как это выглядит в go-ethereum/core/vm/instructions.go, где мы отслеживаем время выполнения:

var (
    bigZero = new(big.Int)
    startTime = time.Now().UnixNano();
)

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
        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
}

Итак go-ethereum/core/vm/instructions.go, это более низкий уровень, чем код, который выдает "Submitted transaction"текст, который находится в go-ethereum/internal/ethapi/api.go, поэтому мы определяем там логическое значение. Если вы попытаетесь определить в нем bool go-ethereum/internal/ethapi/api.go, это не сработает.

Вот как мы устанавливаем bool 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
}

Итак, наконец, у нас есть то, что было указано в OP, или, по крайней мере, разумное приближение к нему, то есть:

INFO [08-09|20:16:38] Submitted transaction                    fullhash=0xa55357ec2488604d580cbdc56373f40ea16dc4cb6aec0ea41a3836c696cc3c17 recipient=0x8705C513da621a16fd1dEFc9dE8aE7CDEAD01Fb8
execute opAdd consume =  1063

Вы можете прочитать код и мой ответ на него на моем GitHub !

Очень интересно узнать, что вы, ребята, думаете об этом решении.

Такие вещи очень крутые. Вероятно, есть масса вещей, которые вы можете сделать в том же духе, но я никогда не углублялся, потому что не мог понять, как защитить свой «хак» от обновленного кода. Есть ли в коде «хуки», позволяющие людям «взламывать» его, или вам просто нужно быть осторожным с обновлениями?
Я думаю, что это вычисляет только один код операции, в большинстве случаев код операции, скомпилированный методом, содержит много opAddинструкций. а иногда метод может вызывать множество других функций и т. д.
Да, верно. Я пробовал это только на одном вызове функции. У вас есть идея, как сделать его более точным?