filtro para restringir la salida de datos de código de operación solo a contratos/funciones llamadas por nodo local

Después de haber modificado el archivo instrucciones.gogeth , puedo ver el tiempo de ejecución de los códigos de operación individuales, se ve así:

ingrese la descripción de la imagen aquí

Mi interpretación de esa salida es que representa la ejecución de todos los contratos de los que escucha mi nodo en ejecución, entonces, todas las transacciones de toda la red (ropsten testnet).

Los cambios que hice en el gethcliente están aquí:

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
}

Lo que me gustaría hacer es restringir de alguna manera esa salida para que solo se muestre para contratos/funciones que implemento desde mi nodo local, es decir, los que yo mismo llamo.

Lo que estoy buscando ahora es, algunas ideas sobre cómo hacer eso, ni siquiera necesariamente una solución, aunque eso sería genial, pero incluso, lugares para comenzar, por ejemplo, algún código que corresponda a un tipo de filtro/bandera similar, ¡Todo ese tipo de cosas, todo ese tipo de ideas serían geniales y útiles!

Respuestas (2)

Leí la fuente de llamada de vm una y otra vez, pero no puedo encontrar una forma válida de calcular el tiempo de ejecución de una sola función (a veces una llamada a otra). cuando implementamos un contrato, esto creará una transacción, el inputatributo es el código de bytes del contrato, si llamamos a un método, primero genera la firma del método (por ejemplo: 0xe079bdf1), luego encuentra este método por firma y ejecuta. Entonces, la única forma de obtener la respuesta es vm opcode, y había leído Solidity Assembly y probado muchas llamadas a métodos, analizado muchos códigos de operación, pero no puedo encontrar una respuesta, es muy difícil para mí. El anuncio de códigos de operación sigue:

.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 

      ......

Tal vez no haya respuesta, tal vez mi método de análisis sea incorrecto. Si alguien sabe la respuesta correcta, por favor dígame. Espero que ayude ~

amigo que te parece esta idea
échale un vistazo- puse mi solución como un awnser- ¿qué te parece?

bien, bueno, es una especie de truco, pero... creo que lo entendí. Así es como funciona:

Me di cuenta de que cada vez que invocamos un contrato localmente, que es lo que estoy tratando de rastrear, lo escuchamos en la consola en forma de "Submitted transaction", así:

ingrese la descripción de la imagen aquí

Lo que hice fue poner una bandera booleana en la función que evoca ese "Submitted transaction"texto, este booleano es el " punto de entrada/puerta de enlace ", por así decirlo, para un envoltorio del código de seguimiento de tiempo.

Así es como se ve en el go-ethereum/core/vm/instructions.go, donde rastreamos el tiempo de ejecución:

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
}

Por lo tanto, go-ethereum/core/vm/instructions.goes un nivel más bajo que el código que escupe el "Submitted transaction"texto, eso está en go-ethereum/internal/ethapi/api.go, por lo que definimos el bool allí. Si intenta definir el bool en go-ethereum/internal/ethapi/api.goél, no funciona.

Así es como configuramos el bool en 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
}

Entonces, finalmente, parece que tenemos lo que se especificó en el OP, o al menos una aproximación razonable, es decir:

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

¡Puedes sacar el código y mi respuesta en mi GitHub !

Muy interesado en saber lo que ustedes piensan de esta solución.

Este tipo de cosas molan mucho. Probablemente hay un montón de cosas que puedes hacer en una línea similar, pero nunca me sumergí porque no podía encontrar la manera de proteger mi 'hackeo' del código actualizado. ¿Hay 'ganchos' en el código para permitir que la gente lo 'piratee', o simplemente hay que tener cuidado con las actualizaciones?
Creo que esto solo calcula un tiempo de código de operación, la mayoría de las veces, un código de operación compilado por un método contiene muchas opAddinstrucciones. y, a veces, un método puede llamar a muchas otras funciones, etc.
Si cierto. Solo lo probé en una llamada de función. ¿Tienes alguna idea de cómo hacerlo más preciso?