¿Las funciones de instrucción makeLog son códigos de operación o no?

El siguiente fragmento de código es una parte constitutiva del instructions.goarchivo, donde viven todos nuestros lieblings opCodes.

// make log instruction function
func makeLog(size int) executionFunc {
    return func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
        topics := make([]common.Hash, size)
        mStart, mSize := stack.pop(), stack.pop()
        for i := 0; i < size; i++ {
            topics[i] = common.BigToHash(stack.pop())
        }

        d := memory.Get(mStart.Int64(), mSize.Int64())
        evm.StateDB.AddLog(&types.Log{
            Address: contract.Address(),
            Topics:  topics,
            Data:    d,
            // This is a non-consensus field, but assigned here because
            // core/state doesn't know the current block number.
            BlockNumber: evm.BlockNumber.Uint64(),
        })

        evm.interpreter.intPool.put(mStart, mSize)
        return nil, nil
    }
}

// make push instruction function
func makePush(size uint64, pushByteSize int) executionFunc {
    return func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
        codeLen := len(contract.Code)

        startMin := codeLen
        if int(*pc+1) < startMin {
            startMin = int(*pc + 1)
        }

        endMin := codeLen
        if startMin+pushByteSize < endMin {
            endMin = startMin + pushByteSize
        }

        integer := evm.interpreter.intPool.get()
        stack.push(integer.SetBytes(common.RightPadBytes(contract.Code[startMin:endMin], pushByteSize)))

        *pc += size
        return nil, nil
    }
}

// make push instruction function
func makeDup(size int64) executionFunc {
    return func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
        stack.dup(evm.interpreter.intPool, int(size))
        return nil, nil
    }
}

// make swap instruction function
func makeSwap(size int64) executionFunc {
    // switch n + 1 otherwise n would be swapped with n
    size += 1
    return func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
        stack.swap(int(size))
        return nil, nil
    }

La pregunta es, ¿son estos make log instruction functionsmismos códigos de operación?

Si lo son, ¿por qué no se llaman así?

Si no, ¿qué están haciendo viviendo en el archivo con todos los opCodes?

Respuestas (1)

No estoy seguro de haber entendido completamente su pregunta, pero aquí están mis observaciones...

Los códigos de operación manejados por las cuatro make*funciones que enumera difieren de los otros códigos de operación de EVM en que cada uno es parte de familias de códigos de operación más amplias:

  • makeLog()maneja códigos de operación LOG0a través deLOG4

  • makePush()maneja códigos de operación PUSH1a través dePUSH32

  • makeDup()maneja códigos de operación DUP1a través deDUP16

  • makeSwap()maneja códigos de operación SWAP1a través deSWAP16

Esto difiere de las otras funciones en el archivo, cada una de las cuales maneja solo un código de operación único, junto con sus operandos de pila.

Además, los LOG*códigos de operación son particularmente inusuales ya que cada uno consume una cantidad diferente de operandos de la pila: LOG0consume 2, LOG4consume 6. Por lo tanto, esto también debe abordarse.

Al final, la función devuelta por cada una de las make*()metafunciones realizará el trabajo de un único código de operación y, por lo tanto, estará en pie de igualdad con las demás funciones del archivo.