Следующий фрагмент кода является составной частью instructions.go
файла, в котором живут 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
}
Вопрос в том, являются ли они make log instruction functions
сами кодами операций?
Если они есть, то почему они не называются так?
Если нет, то что они делают, живя в файле со всеми opCodes
?
Не уверен, что я полностью понял ваш вопрос, но вот мои наблюдения...
Коды операций, обрабатываемые четырьмя make*
перечисленными вами функциями, отличаются от других кодов операций EVM тем, что они являются частью более широких семейств кодов операций:
makeLog()
обрабатывает коды операций LOG0
черезLOG4
makePush()
обрабатывает коды операций PUSH1
черезPUSH32
makeDup()
обрабатывает коды операций DUP1
черезDUP16
makeSwap()
обрабатывает коды операций SWAP1
черезSWAP16
Это отличается от других функций в файле, каждая из которых обрабатывает только один код операции вместе со своими операндами стека.
Кроме того, LOG*
коды операций особенно необычны, поскольку каждый из них использует разное количество операндов стека: LOG0
потребляет 2, LOG4
потребляет 6. Так что с этим тоже нужно разобраться.
В конце концов, функция, возвращаемая каждой из make*()
метафункций, будет выполнять работу одного кода операции и, следовательно, находится на равных условиях с другими функциями в файле.