mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 18:02:24 +00:00
core/vm/runtime: utilize the programs a bit
This commit is contained in:
parent
659cd13c1f
commit
32b1831920
2 changed files with 69 additions and 117 deletions
|
|
@ -149,11 +149,11 @@ func (p *Program) ExtcodeCopy(address, memOffset, codeOffset, length any) *Progr
|
||||||
// Call is a convenience function to make a call. If 'gas' is nil, the opcode GAS will
|
// Call is a convenience function to make a call. If 'gas' is nil, the opcode GAS will
|
||||||
// be used to provide all gas.
|
// be used to provide all gas.
|
||||||
func (p *Program) Call(gas *big.Int, address, value, inOffset, inSize, outOffset, outSize any) *Program {
|
func (p *Program) Call(gas *big.Int, address, value, inOffset, inSize, outOffset, outSize any) *Program {
|
||||||
p.Push(outSize)
|
if outOffset == outSize && inSize == outSize && inOffset == outSize && value == outSize {
|
||||||
p.Push(outOffset)
|
p.Push(outSize).Ops(vm.DUP1, vm.DUP1, vm.DUP1, vm.DUP1)
|
||||||
p.Push(inSize)
|
} else {
|
||||||
p.Push(inOffset)
|
p.Push(outSize).Push(outOffset).Push(inSize).Push(inOffset).Push(value)
|
||||||
p.Push(value)
|
}
|
||||||
p.Push(address)
|
p.Push(address)
|
||||||
if gas == nil {
|
if gas == nil {
|
||||||
p.Op(vm.GAS)
|
p.Op(vm.GAS)
|
||||||
|
|
@ -166,10 +166,11 @@ func (p *Program) Call(gas *big.Int, address, value, inOffset, inSize, outOffset
|
||||||
// DelegateCall is a convenience function to make a delegatecall. If 'gas' is nil, the opcode GAS will
|
// DelegateCall is a convenience function to make a delegatecall. If 'gas' is nil, the opcode GAS will
|
||||||
// be used to provide all gas.
|
// be used to provide all gas.
|
||||||
func (p *Program) DelegateCall(gas *big.Int, address, inOffset, inSize, outOffset, outSize any) *Program {
|
func (p *Program) DelegateCall(gas *big.Int, address, inOffset, inSize, outOffset, outSize any) *Program {
|
||||||
p.Push(outSize)
|
if outOffset == outSize && inSize == outSize && inOffset == outSize {
|
||||||
p.Push(outOffset)
|
p.Push(outSize).Ops(vm.DUP1, vm.DUP1, vm.DUP1)
|
||||||
p.Push(inSize)
|
} else {
|
||||||
p.Push(inOffset)
|
p.Push(outSize).Push(outOffset).Push(inSize).Push(inOffset)
|
||||||
|
}
|
||||||
p.Push(address)
|
p.Push(address)
|
||||||
if gas == nil {
|
if gas == nil {
|
||||||
p.Op(vm.GAS)
|
p.Op(vm.GAS)
|
||||||
|
|
@ -182,10 +183,11 @@ func (p *Program) DelegateCall(gas *big.Int, address, inOffset, inSize, outOffse
|
||||||
// StaticCall is a convenience function to make a staticcall. If 'gas' is nil, the opcode GAS will
|
// StaticCall is a convenience function to make a staticcall. If 'gas' is nil, the opcode GAS will
|
||||||
// be used to provide all gas.
|
// be used to provide all gas.
|
||||||
func (p *Program) StaticCall(gas *big.Int, address, inOffset, inSize, outOffset, outSize any) *Program {
|
func (p *Program) StaticCall(gas *big.Int, address, inOffset, inSize, outOffset, outSize any) *Program {
|
||||||
p.Push(outSize)
|
if outOffset == outSize && inSize == outSize && inOffset == outSize {
|
||||||
p.Push(outOffset)
|
p.Push(outSize).Ops(vm.DUP1, vm.DUP1, vm.DUP1)
|
||||||
p.Push(inSize)
|
} else {
|
||||||
p.Push(inOffset)
|
p.Push(outSize).Push(outOffset).Push(inSize).Push(inOffset)
|
||||||
|
}
|
||||||
p.Push(address)
|
p.Push(address)
|
||||||
if gas == nil {
|
if gas == nil {
|
||||||
p.Op(vm.GAS)
|
p.Op(vm.GAS)
|
||||||
|
|
@ -198,10 +200,11 @@ func (p *Program) StaticCall(gas *big.Int, address, inOffset, inSize, outOffset,
|
||||||
// StaticCall is a convenience function to make a callcode. If 'gas' is nil, the opcode GAS will
|
// StaticCall is a convenience function to make a callcode. If 'gas' is nil, the opcode GAS will
|
||||||
// be used to provide all gas.
|
// be used to provide all gas.
|
||||||
func (p *Program) CallCode(gas *big.Int, address, value, inOffset, inSize, outOffset, outSize any) *Program {
|
func (p *Program) CallCode(gas *big.Int, address, value, inOffset, inSize, outOffset, outSize any) *Program {
|
||||||
p.Push(outSize)
|
if outOffset == outSize && inSize == outSize && inOffset == outSize {
|
||||||
p.Push(outOffset)
|
p.Push(outSize).Ops(vm.DUP1, vm.DUP1, vm.DUP1)
|
||||||
p.Push(inSize)
|
} else {
|
||||||
p.Push(inOffset)
|
p.Push(outSize).Push(outOffset).Push(inSize).Push(inOffset)
|
||||||
|
}
|
||||||
p.Push(value)
|
p.Push(value)
|
||||||
p.Push(address)
|
p.Push(address)
|
||||||
if gas == nil {
|
if gas == nil {
|
||||||
|
|
@ -218,16 +221,17 @@ func (p *Program) Label() uint64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jumpdest adds a JUMPDEST op, and returns the PC of that instruction
|
// Jumpdest adds a JUMPDEST op, and returns the PC of that instruction
|
||||||
func (p *Program) Jumpdest() uint64 {
|
func (p *Program) Jumpdest() (*Program, uint64) {
|
||||||
here := p.Label()
|
here := p.Label()
|
||||||
p.Op(vm.JUMPDEST)
|
p.Op(vm.JUMPDEST)
|
||||||
return here
|
return p, here
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jump pushes the destination and adds a JUMP
|
// Jump pushes the destination and adds a JUMP
|
||||||
func (p *Program) Jump(loc any) {
|
func (p *Program) Jump(loc any) *Program {
|
||||||
p.Push(loc)
|
p.Push(loc)
|
||||||
p.Op(vm.JUMP)
|
p.Op(vm.JUMP)
|
||||||
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jump pushes the destination and adds a JUMP
|
// Jump pushes the destination and adds a JUMP
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm/program"
|
||||||
"github.com/ethereum/go-ethereum/eth/tracers"
|
"github.com/ethereum/go-ethereum/eth/tracers"
|
||||||
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
@ -436,110 +437,57 @@ func benchmarkNonModifyingCode(gas uint64, code []byte, name string, tracerCode
|
||||||
// BenchmarkSimpleLoop test a pretty simple loop which loops until OOG
|
// BenchmarkSimpleLoop test a pretty simple loop which loops until OOG
|
||||||
// 55 ms
|
// 55 ms
|
||||||
func BenchmarkSimpleLoop(b *testing.B) {
|
func BenchmarkSimpleLoop(b *testing.B) {
|
||||||
staticCallIdentity := []byte{
|
|
||||||
byte(vm.JUMPDEST), // [ count ]
|
|
||||||
// push args for the call
|
|
||||||
byte(vm.PUSH1), 0, // out size
|
|
||||||
byte(vm.DUP1), // out offset
|
|
||||||
byte(vm.DUP1), // out insize
|
|
||||||
byte(vm.DUP1), // in offset
|
|
||||||
byte(vm.PUSH1), 0x4, // address of identity
|
|
||||||
byte(vm.GAS), // gas
|
|
||||||
byte(vm.STATICCALL),
|
|
||||||
byte(vm.POP), // pop return value
|
|
||||||
byte(vm.PUSH1), 0, // jumpdestination
|
|
||||||
byte(vm.JUMP),
|
|
||||||
}
|
|
||||||
|
|
||||||
callIdentity := []byte{
|
p, lbl := program.New().Jumpdest()
|
||||||
byte(vm.JUMPDEST), // [ count ]
|
// Call identity, and pop return value
|
||||||
// push args for the call
|
staticCallIdentity := p.
|
||||||
byte(vm.PUSH1), 0, // out size
|
StaticCall(nil, 0x4, 0, 0, 0, 0).
|
||||||
byte(vm.DUP1), // out offset
|
Op(vm.POP). // pop return value
|
||||||
byte(vm.DUP1), // out insize
|
Jump(lbl). // jump to label
|
||||||
byte(vm.DUP1), // in offset
|
Bytecode()
|
||||||
byte(vm.DUP1), // value
|
|
||||||
byte(vm.PUSH1), 0x4, // address of identity
|
|
||||||
byte(vm.GAS), // gas
|
|
||||||
byte(vm.CALL),
|
|
||||||
byte(vm.POP), // pop return value
|
|
||||||
byte(vm.PUSH1), 0, // jumpdestination
|
|
||||||
byte(vm.JUMP),
|
|
||||||
}
|
|
||||||
|
|
||||||
callInexistant := []byte{
|
p, lbl = program.New().Jumpdest()
|
||||||
byte(vm.JUMPDEST), // [ count ]
|
callIdentity := p.
|
||||||
// push args for the call
|
Call(nil, 0x4, 0, 0, 0, 0, 0).
|
||||||
byte(vm.PUSH1), 0, // out size
|
Op(vm.POP). // pop return value
|
||||||
byte(vm.DUP1), // out offset
|
Jump(lbl). // jump to label
|
||||||
byte(vm.DUP1), // out insize
|
Bytecode()
|
||||||
byte(vm.DUP1), // in offset
|
|
||||||
byte(vm.DUP1), // value
|
|
||||||
byte(vm.PUSH1), 0xff, // address of existing contract
|
|
||||||
byte(vm.GAS), // gas
|
|
||||||
byte(vm.CALL),
|
|
||||||
byte(vm.POP), // pop return value
|
|
||||||
byte(vm.PUSH1), 0, // jumpdestination
|
|
||||||
byte(vm.JUMP),
|
|
||||||
}
|
|
||||||
|
|
||||||
callEOA := []byte{
|
p, lbl = program.New().Jumpdest()
|
||||||
byte(vm.JUMPDEST), // [ count ]
|
callInexistant := p.
|
||||||
// push args for the call
|
Call(nil, 0xff, 0, 0, 0, 0, 0).
|
||||||
byte(vm.PUSH1), 0, // out size
|
Op(vm.POP). // pop return value
|
||||||
byte(vm.DUP1), // out offset
|
Jump(lbl). // jump to label
|
||||||
byte(vm.DUP1), // out insize
|
Bytecode()
|
||||||
byte(vm.DUP1), // in offset
|
|
||||||
byte(vm.DUP1), // value
|
|
||||||
byte(vm.PUSH1), 0xE0, // address of EOA
|
|
||||||
byte(vm.GAS), // gas
|
|
||||||
byte(vm.CALL),
|
|
||||||
byte(vm.POP), // pop return value
|
|
||||||
byte(vm.PUSH1), 0, // jumpdestination
|
|
||||||
byte(vm.JUMP),
|
|
||||||
}
|
|
||||||
|
|
||||||
loopingCode := []byte{
|
p, lbl = program.New().Jumpdest()
|
||||||
byte(vm.JUMPDEST), // [ count ]
|
callEOA := p.
|
||||||
// push args for the call
|
Call(nil, 0xE0, 0, 0, 0, 0, 0). // call addr of EOA
|
||||||
byte(vm.PUSH1), 0, // out size
|
Op(vm.POP). // pop return value
|
||||||
byte(vm.DUP1), // out offset
|
Jump(lbl). // jump to label
|
||||||
byte(vm.DUP1), // out insize
|
Bytecode()
|
||||||
byte(vm.DUP1), // in offset
|
|
||||||
byte(vm.PUSH1), 0x4, // address of identity
|
|
||||||
byte(vm.GAS), // gas
|
|
||||||
|
|
||||||
byte(vm.POP), byte(vm.POP), byte(vm.POP), byte(vm.POP), byte(vm.POP), byte(vm.POP),
|
p, lbl = program.New().Jumpdest()
|
||||||
byte(vm.PUSH1), 0, // jumpdestination
|
// Push as if we were making call, then pop it off again, and loop
|
||||||
byte(vm.JUMP),
|
loopingCode := p.Push(0).
|
||||||
}
|
Ops(vm.DUP1, vm.DUP1, vm.DUP1).
|
||||||
|
Push(0x4).
|
||||||
|
Ops(vm.GAS, vm.POP, vm.POP, vm.POP, vm.POP, vm.POP, vm.POP).
|
||||||
|
Jump(lbl).Bytecode()
|
||||||
|
|
||||||
loopingCode2 := []byte{
|
p, lbl = program.New().Jumpdest()
|
||||||
byte(vm.JUMPDEST), // [ count ]
|
loopingCode2 := p.
|
||||||
// push args for the call
|
Push(0x01020304).Push(0x0102030405).
|
||||||
byte(vm.PUSH4), 1, 2, 3, 4,
|
Ops(vm.POP, vm.POP).
|
||||||
byte(vm.PUSH5), 1, 2, 3, 4, 5,
|
Op(vm.PUSH6).Append(make([]byte, 6)).Op(vm.JUMP). // Jumpdest zero expressed in 6 bytes
|
||||||
|
Bytecode()
|
||||||
|
|
||||||
byte(vm.POP), byte(vm.POP),
|
p, lbl = program.New().Jumpdest()
|
||||||
byte(vm.PUSH6), 0, 0, 0, 0, 0, 0, // jumpdestination
|
callRevertingContractWithInput := p.
|
||||||
byte(vm.JUMP),
|
Call(nil, 0xee, 0, 0, 0x20, 0x0, 0x0).
|
||||||
}
|
Op(vm.POP).
|
||||||
|
Jump(lbl).
|
||||||
callRevertingContractWithInput := []byte{
|
Bytecode()
|
||||||
byte(vm.JUMPDEST), //
|
|
||||||
// push args for the call
|
|
||||||
byte(vm.PUSH1), 0, // out size
|
|
||||||
byte(vm.DUP1), // out offset
|
|
||||||
byte(vm.PUSH1), 0x20, // in size
|
|
||||||
byte(vm.PUSH1), 0x00, // in offset
|
|
||||||
byte(vm.PUSH1), 0x00, // value
|
|
||||||
byte(vm.PUSH1), 0xEE, // address of reverting contract
|
|
||||||
byte(vm.GAS), // gas
|
|
||||||
byte(vm.CALL),
|
|
||||||
byte(vm.POP), // pop return value
|
|
||||||
byte(vm.PUSH1), 0, // jumpdestination
|
|
||||||
byte(vm.JUMP),
|
|
||||||
}
|
|
||||||
|
|
||||||
//tracer := logger.NewJSONLogger(nil, os.Stdout)
|
//tracer := logger.NewJSONLogger(nil, os.Stdout)
|
||||||
//Execute(loopingCode, nil, &Config{
|
//Execute(loopingCode, nil, &Config{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue