mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 18:02:24 +00:00
core/vm/program: minor UX tweaks
This commit is contained in:
parent
6d7e9b9b82
commit
55edee5565
3 changed files with 178 additions and 105 deletions
|
|
@ -127,14 +127,14 @@ func (p *Program) Push0() *Program {
|
||||||
return p.Op(vm.PUSH0)
|
return p.Op(vm.PUSH0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bytecode returns the Program bytecode
|
// Bytes returns the Program bytecode
|
||||||
func (p *Program) Bytecode() []byte {
|
func (p *Program) Bytes() []byte {
|
||||||
return p.code
|
return p.code
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hex returns the Program bytecode as a hex string
|
// Hex returns the Program bytecode as a hex string
|
||||||
func (p *Program) Hex() string {
|
func (p *Program) Hex() string {
|
||||||
return fmt.Sprintf("%02x", p.Bytecode())
|
return fmt.Sprintf("%02x", p.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExtcodeCopy performsa an extcodecopy invocation
|
// ExtcodeCopy performsa an extcodecopy invocation
|
||||||
|
|
@ -280,6 +280,29 @@ func (p *Program) Mstore(data []byte, memStart uint32) *Program {
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MstorePadded stores the provided data (into the memory area starting at memStart).
|
||||||
|
// If data does not align on 32 bytes, it will be LHS-padded.
|
||||||
|
// For example, providing data 0x1122, it will do a PUSH2:
|
||||||
|
// PUSH2 0x1122, resulting in
|
||||||
|
// stack: 0x0000000000000000000000000000000000000000000000000000000000001122
|
||||||
|
// followed by MSTORE(0,0)
|
||||||
|
// And thus, the resulting memory will be
|
||||||
|
// [ 0000000000000000000000000000000000000000000000000000000000001122 ]
|
||||||
|
func (p *Program) MstorePadded(data []byte, memStart uint32) *Program {
|
||||||
|
var idx = 0
|
||||||
|
// We need to store it in chunks of 32 bytes
|
||||||
|
for ; idx < len(data); idx += 32 {
|
||||||
|
end := min(len(data), idx+32)
|
||||||
|
chunk := data[idx:end]
|
||||||
|
// push the value
|
||||||
|
p.Push(chunk)
|
||||||
|
// push the memory index
|
||||||
|
p.Push(uint32(idx) + memStart)
|
||||||
|
p.Op(vm.MSTORE)
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
// MemToStorage copies the given memory area into SSTORE slots,
|
// MemToStorage copies the given memory area into SSTORE slots,
|
||||||
// It expects data to be aligned to 32 byte, and does not zero out
|
// It expects data to be aligned to 32 byte, and does not zero out
|
||||||
// remainders if some data is not
|
// remainders if some data is not
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,7 @@ func TestCreateAndCall(t *testing.T) {
|
||||||
deployed.Return(0, 32)
|
deployed.Return(0, 32)
|
||||||
|
|
||||||
// Pack them
|
// Pack them
|
||||||
ctor.ReturnData(deployed.Bytecode())
|
ctor.ReturnData(deployed.Bytes())
|
||||||
// Verify constructor + runtime code
|
// Verify constructor + runtime code
|
||||||
{
|
{
|
||||||
want := "6005600055606060005360006001536054600253606060035360006004536052600553606060065360206007536060600853600060095360f3600a53600b6000f3"
|
want := "6005600055606060005360006001536054600253606060035360006004536052600553606060065360206007536060600853600060095360f3600a53600b6000f3"
|
||||||
|
|
@ -155,21 +155,134 @@ func TestCreateAndCall(t *testing.T) {
|
||||||
|
|
||||||
func TestCreate2Call(t *testing.T) {
|
func TestCreate2Call(t *testing.T) {
|
||||||
// Some runtime code
|
// Some runtime code
|
||||||
runtime := New().Ops(vm.ADDRESS, vm.SELFDESTRUCT).Bytecode()
|
runtime := New().Ops(vm.ADDRESS, vm.SELFDESTRUCT).Bytes()
|
||||||
want := common.FromHex("0x30ff")
|
want := common.FromHex("0x30ff")
|
||||||
if !bytes.Equal(want, runtime) {
|
if !bytes.Equal(want, runtime) {
|
||||||
t.Fatalf("runtime code error\nwant: %x\nhave: %x\n", want, runtime)
|
t.Fatalf("runtime code error\nwant: %x\nhave: %x\n", want, runtime)
|
||||||
}
|
}
|
||||||
// A constructor returning the runtime code
|
// A constructor returning the runtime code
|
||||||
initcode := New().ReturnData(runtime).Bytecode()
|
initcode := New().ReturnData(runtime).Bytes()
|
||||||
want = common.FromHex("603060005360ff60015360026000f3")
|
want = common.FromHex("603060005360ff60015360026000f3")
|
||||||
if !bytes.Equal(want, initcode) {
|
if !bytes.Equal(want, initcode) {
|
||||||
t.Fatalf("initcode error\nwant: %x\nhave: %x\n", want, initcode)
|
t.Fatalf("initcode error\nwant: %x\nhave: %x\n", want, initcode)
|
||||||
}
|
}
|
||||||
// A factory invoking the constructor
|
// A factory invoking the constructor
|
||||||
outer := New().Create2AndCall(initcode, nil).Bytecode()
|
outer := New().Create2AndCall(initcode, nil).Bytes()
|
||||||
want = common.FromHex("60606000536030600153606060025360006003536053600453606060055360ff6006536060600753600160085360536009536060600a536002600b536060600c536000600d5360f3600e536000600f60006000f560006000600060006000855af15050")
|
want = common.FromHex("60606000536030600153606060025360006003536053600453606060055360ff6006536060600753600160085360536009536060600a536002600b536060600c536000600d5360f3600e536000600f60006000f560006000600060006000855af15050")
|
||||||
if !bytes.Equal(want, outer) {
|
if !bytes.Equal(want, outer) {
|
||||||
t.Fatalf("factory error\nwant: %x\nhave: %x\n", want, outer)
|
t.Fatalf("factory error\nwant: %x\nhave: %x\n", want, outer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGenerator(t *testing.T) {
|
||||||
|
for i, tc := range []struct {
|
||||||
|
want []byte
|
||||||
|
haveFn func() []byte
|
||||||
|
}{
|
||||||
|
{ // CREATE
|
||||||
|
want: []byte{
|
||||||
|
// Store initcode in memory at 0x00 (5 bytes left-padded to 32 bytes)
|
||||||
|
byte(vm.PUSH5),
|
||||||
|
// Init code: PUSH1 0, PUSH1 0, RETURN (3 steps)
|
||||||
|
byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.RETURN),
|
||||||
|
byte(vm.PUSH1), 0,
|
||||||
|
byte(vm.MSTORE),
|
||||||
|
// length, offset, value
|
||||||
|
byte(vm.PUSH1), 5, byte(vm.PUSH1), 27, byte(vm.PUSH1), 0,
|
||||||
|
byte(vm.CREATE),
|
||||||
|
byte(vm.POP),
|
||||||
|
},
|
||||||
|
haveFn: func() []byte {
|
||||||
|
initcode := New().Return(0, 0).Bytes()
|
||||||
|
return New().MstorePadded(initcode, 0).
|
||||||
|
Push(len(initcode)). // length
|
||||||
|
Push(32 - len(initcode)). // offset
|
||||||
|
Push(0). // value
|
||||||
|
Op(vm.CREATE).
|
||||||
|
Op(vm.POP).Bytes()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ // CREATE2
|
||||||
|
want: []byte{
|
||||||
|
// Store initcode in memory at 0x00 (5 bytes left-padded to 32 bytes)
|
||||||
|
byte(vm.PUSH5),
|
||||||
|
// Init code: PUSH1 0, PUSH1 0, RETURN (3 steps)
|
||||||
|
byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.RETURN),
|
||||||
|
byte(vm.PUSH1), 0,
|
||||||
|
byte(vm.MSTORE),
|
||||||
|
// salt, length, offset, value
|
||||||
|
byte(vm.PUSH1), 1, byte(vm.PUSH1), 5, byte(vm.PUSH1), 27, byte(vm.PUSH1), 0,
|
||||||
|
byte(vm.CREATE2),
|
||||||
|
byte(vm.POP),
|
||||||
|
},
|
||||||
|
haveFn: func() []byte {
|
||||||
|
initcode := New().Return(0, 0).Bytes()
|
||||||
|
return New().MstorePadded(initcode, 0).
|
||||||
|
Push(1). // salt
|
||||||
|
Push(len(initcode)). // length
|
||||||
|
Push(32 - len(initcode)). // offset
|
||||||
|
Push(0). // value
|
||||||
|
Op(vm.CREATE2).
|
||||||
|
Op(vm.POP).Bytes()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ // CALL
|
||||||
|
want: []byte{
|
||||||
|
// outsize, outoffset, insize, inoffset
|
||||||
|
byte(vm.PUSH1), 0, byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1),
|
||||||
|
byte(vm.DUP1), // value
|
||||||
|
byte(vm.PUSH1), 0xbb, //address
|
||||||
|
byte(vm.GAS), // gas
|
||||||
|
byte(vm.CALL),
|
||||||
|
byte(vm.POP),
|
||||||
|
},
|
||||||
|
haveFn: func() []byte {
|
||||||
|
return New().Call(nil, 0xbb, 0, 0, 0, 0, 0).Op(vm.POP).Bytes()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ // CALLCODE
|
||||||
|
want: []byte{
|
||||||
|
// outsize, outoffset, insize, inoffset
|
||||||
|
byte(vm.PUSH1), 0, byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1),
|
||||||
|
byte(vm.PUSH1), 0, // value
|
||||||
|
byte(vm.PUSH1), 0xcc, //address
|
||||||
|
byte(vm.GAS), // gas
|
||||||
|
byte(vm.CALLCODE),
|
||||||
|
byte(vm.POP),
|
||||||
|
},
|
||||||
|
haveFn: func() []byte {
|
||||||
|
return New().CallCode(nil, 0xcc, 0, 0, 0, 0, 0).Op(vm.POP).Bytes()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ // STATICCALL
|
||||||
|
want: []byte{
|
||||||
|
// outsize, outoffset, insize, inoffset
|
||||||
|
byte(vm.PUSH1), 0, byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1),
|
||||||
|
byte(vm.PUSH1), 0xdd, //address
|
||||||
|
byte(vm.GAS), // gas
|
||||||
|
byte(vm.STATICCALL),
|
||||||
|
byte(vm.POP),
|
||||||
|
},
|
||||||
|
haveFn: func() []byte {
|
||||||
|
return New().StaticCall(nil, 0xdd, 0, 0, 0, 0).Op(vm.POP).Bytes()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ // DELEGATECALL
|
||||||
|
want: []byte{
|
||||||
|
// outsize, outoffset, insize, inoffset
|
||||||
|
byte(vm.PUSH1), 0, byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1),
|
||||||
|
byte(vm.PUSH1), 0xee, //address
|
||||||
|
byte(vm.GAS), // gas
|
||||||
|
byte(vm.DELEGATECALL),
|
||||||
|
byte(vm.POP),
|
||||||
|
},
|
||||||
|
haveFn: func() []byte {
|
||||||
|
return New().DelegateCall(nil, 0xee, 0, 0, 0, 0).Op(vm.POP).Bytes()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
if have := tc.haveFn(); !bytes.Equal(have, tc.want) {
|
||||||
|
t.Fatalf("test %d error\nhave: %x\nwant: %x\n", i, have, tc.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -442,22 +442,22 @@ func BenchmarkSimpleLoop(b *testing.B) {
|
||||||
// Call identity, and pop return value
|
// Call identity, and pop return value
|
||||||
staticCallIdentity := p.
|
staticCallIdentity := p.
|
||||||
StaticCall(nil, 0x4, 0, 0, 0, 0).
|
StaticCall(nil, 0x4, 0, 0, 0, 0).
|
||||||
Op(vm.POP).Jump(lbl).Bytecode() // pop return value and jump to label
|
Op(vm.POP).Jump(lbl).Bytes() // pop return value and jump to label
|
||||||
|
|
||||||
p, lbl = program.New().Jumpdest()
|
p, lbl = program.New().Jumpdest()
|
||||||
callIdentity := p.
|
callIdentity := p.
|
||||||
Call(nil, 0x4, 0, 0, 0, 0, 0).
|
Call(nil, 0x4, 0, 0, 0, 0, 0).
|
||||||
Op(vm.POP).Jump(lbl).Bytecode() // pop return value and jump to label
|
Op(vm.POP).Jump(lbl).Bytes() // pop return value and jump to label
|
||||||
|
|
||||||
p, lbl = program.New().Jumpdest()
|
p, lbl = program.New().Jumpdest()
|
||||||
callInexistant := p.
|
callInexistant := p.
|
||||||
Call(nil, 0xff, 0, 0, 0, 0, 0).
|
Call(nil, 0xff, 0, 0, 0, 0, 0).
|
||||||
Op(vm.POP).Jump(lbl).Bytecode() // pop return value and jump to label
|
Op(vm.POP).Jump(lbl).Bytes() // pop return value and jump to label
|
||||||
|
|
||||||
p, lbl = program.New().Jumpdest()
|
p, lbl = program.New().Jumpdest()
|
||||||
callEOA := p.
|
callEOA := p.
|
||||||
Call(nil, 0xE0, 0, 0, 0, 0, 0). // call addr of EOA
|
Call(nil, 0xE0, 0, 0, 0, 0, 0). // call addr of EOA
|
||||||
Op(vm.POP).Jump(lbl).Bytecode() // pop return value and jump to label
|
Op(vm.POP).Jump(lbl).Bytes() // pop return value and jump to label
|
||||||
|
|
||||||
p, lbl = program.New().Jumpdest()
|
p, lbl = program.New().Jumpdest()
|
||||||
// Push as if we were making call, then pop it off again, and loop
|
// Push as if we were making call, then pop it off again, and loop
|
||||||
|
|
@ -465,19 +465,19 @@ func BenchmarkSimpleLoop(b *testing.B) {
|
||||||
Ops(vm.DUP1, vm.DUP1, vm.DUP1).
|
Ops(vm.DUP1, vm.DUP1, vm.DUP1).
|
||||||
Push(0x4).
|
Push(0x4).
|
||||||
Ops(vm.GAS, vm.POP, vm.POP, vm.POP, vm.POP, vm.POP, vm.POP).
|
Ops(vm.GAS, vm.POP, vm.POP, vm.POP, vm.POP, vm.POP, vm.POP).
|
||||||
Jump(lbl).Bytecode()
|
Jump(lbl).Bytes()
|
||||||
|
|
||||||
p, lbl = program.New().Jumpdest()
|
p, lbl = program.New().Jumpdest()
|
||||||
loopingCode2 := p.
|
loopingCode2 := p.
|
||||||
Push(0x01020304).Push(uint64(0x0102030405)).
|
Push(0x01020304).Push(uint64(0x0102030405)).
|
||||||
Ops(vm.POP, vm.POP).
|
Ops(vm.POP, vm.POP).
|
||||||
Op(vm.PUSH6).Append(make([]byte, 6)).Op(vm.JUMP). // Jumpdest zero expressed in 6 bytes
|
Op(vm.PUSH6).Append(make([]byte, 6)).Op(vm.JUMP). // Jumpdest zero expressed in 6 bytes
|
||||||
Bytecode()
|
Bytes()
|
||||||
|
|
||||||
p, lbl = program.New().Jumpdest()
|
p, lbl = program.New().Jumpdest()
|
||||||
callRevertingContractWithInput := p.
|
callRevertingContractWithInput := p.
|
||||||
Call(nil, 0xee, 0, 0, 0x20, 0x0, 0x0).
|
Call(nil, 0xee, 0, 0, 0x20, 0x0, 0x0).
|
||||||
Op(vm.POP).Jump(lbl).Bytecode() // pop return value and jump to label
|
Op(vm.POP).Jump(lbl).Bytes() // pop return value and jump to label
|
||||||
|
|
||||||
//tracer := logger.NewJSONLogger(nil, os.Stdout)
|
//tracer := logger.NewJSONLogger(nil, os.Stdout)
|
||||||
//Execute(loopingCode, nil, &Config{
|
//Execute(loopingCode, nil, &Config{
|
||||||
|
|
@ -716,104 +716,49 @@ func TestRuntimeJSTracer(t *testing.T) {
|
||||||
this.exits++;
|
this.exits++;
|
||||||
this.gasUsed = res.getGasUsed();
|
this.gasUsed = res.getGasUsed();
|
||||||
}}`}
|
}}`}
|
||||||
|
initcode := program.New().Return(0, 0).Bytes()
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
code []byte
|
code []byte
|
||||||
// One result per tracer
|
// One result per tracer
|
||||||
results []string
|
results []string
|
||||||
}{
|
}{
|
||||||
{
|
{ // CREATE
|
||||||
// CREATE
|
code: program.New().MstorePadded(initcode, 0).
|
||||||
code: []byte{
|
Push(len(initcode)). // length
|
||||||
// Store initcode in memory at 0x00 (5 bytes left-padded to 32 bytes)
|
Push(32 - len(initcode)). // offset
|
||||||
byte(vm.PUSH5),
|
Push(0). // value
|
||||||
// Init code: PUSH1 0, PUSH1 0, RETURN (3 steps)
|
Op(vm.CREATE).
|
||||||
byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.RETURN),
|
Op(vm.POP).Bytes(),
|
||||||
byte(vm.PUSH1), 0,
|
|
||||||
byte(vm.MSTORE),
|
|
||||||
// length, offset, value
|
|
||||||
byte(vm.PUSH1), 5, byte(vm.PUSH1), 27, byte(vm.PUSH1), 0,
|
|
||||||
byte(vm.CREATE),
|
|
||||||
byte(vm.POP),
|
|
||||||
},
|
|
||||||
results: []string{`"1,1,952853,6,12"`, `"1,1,952853,6,0"`},
|
results: []string{`"1,1,952853,6,12"`, `"1,1,952853,6,0"`},
|
||||||
},
|
},
|
||||||
{
|
{ // CREATE2
|
||||||
// CREATE2
|
code: program.New().MstorePadded(initcode, 0).
|
||||||
code: []byte{
|
Push(1). // salt
|
||||||
// Store initcode in memory at 0x00 (5 bytes left-padded to 32 bytes)
|
Push(len(initcode)). // length
|
||||||
byte(vm.PUSH5),
|
Push(32 - len(initcode)). // offset
|
||||||
// Init code: PUSH1 0, PUSH1 0, RETURN (3 steps)
|
Push(0). // value
|
||||||
byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.RETURN),
|
Op(vm.CREATE2).
|
||||||
byte(vm.PUSH1), 0,
|
Op(vm.POP).Bytes(),
|
||||||
byte(vm.MSTORE),
|
|
||||||
// salt, length, offset, value
|
|
||||||
byte(vm.PUSH1), 1, byte(vm.PUSH1), 5, byte(vm.PUSH1), 27, byte(vm.PUSH1), 0,
|
|
||||||
byte(vm.CREATE2),
|
|
||||||
byte(vm.POP),
|
|
||||||
},
|
|
||||||
results: []string{`"1,1,952844,6,13"`, `"1,1,952844,6,0"`},
|
results: []string{`"1,1,952844,6,13"`, `"1,1,952844,6,0"`},
|
||||||
},
|
},
|
||||||
{
|
{ // CALL
|
||||||
// CALL
|
code: program.New().Call(nil, 0xbb, 0, 0, 0, 0, 0).Op(vm.POP).Bytes(),
|
||||||
code: []byte{
|
|
||||||
// outsize, outoffset, insize, inoffset
|
|
||||||
byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0,
|
|
||||||
byte(vm.PUSH1), 0, // value
|
|
||||||
byte(vm.PUSH1), 0xbb, //address
|
|
||||||
byte(vm.GAS), // gas
|
|
||||||
byte(vm.CALL),
|
|
||||||
byte(vm.POP),
|
|
||||||
},
|
|
||||||
results: []string{`"1,1,981796,6,13"`, `"1,1,981796,6,0"`},
|
results: []string{`"1,1,981796,6,13"`, `"1,1,981796,6,0"`},
|
||||||
},
|
},
|
||||||
{
|
{ // CALLCODE
|
||||||
// CALLCODE
|
code: program.New().CallCode(nil, 0xcc, 0, 0, 0, 0, 0).Op(vm.POP).Bytes(),
|
||||||
code: []byte{
|
|
||||||
// outsize, outoffset, insize, inoffset
|
|
||||||
byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0,
|
|
||||||
byte(vm.PUSH1), 0, // value
|
|
||||||
byte(vm.PUSH1), 0xcc, //address
|
|
||||||
byte(vm.GAS), // gas
|
|
||||||
byte(vm.CALLCODE),
|
|
||||||
byte(vm.POP),
|
|
||||||
},
|
|
||||||
results: []string{`"1,1,981796,6,13"`, `"1,1,981796,6,0"`},
|
results: []string{`"1,1,981796,6,13"`, `"1,1,981796,6,0"`},
|
||||||
},
|
},
|
||||||
{
|
{ // STATICCALL
|
||||||
// STATICCALL
|
code: program.New().StaticCall(nil, 0xdd, 0, 0, 0, 0).Op(vm.POP).Bytes(),
|
||||||
code: []byte{
|
|
||||||
// outsize, outoffset, insize, inoffset
|
|
||||||
byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0,
|
|
||||||
byte(vm.PUSH1), 0xdd, //address
|
|
||||||
byte(vm.GAS), // gas
|
|
||||||
byte(vm.STATICCALL),
|
|
||||||
byte(vm.POP),
|
|
||||||
},
|
|
||||||
results: []string{`"1,1,981799,6,12"`, `"1,1,981799,6,0"`},
|
results: []string{`"1,1,981799,6,12"`, `"1,1,981799,6,0"`},
|
||||||
},
|
},
|
||||||
{
|
{ // DELEGATECALL
|
||||||
// DELEGATECALL
|
code: program.New().DelegateCall(nil, 0xee, 0, 0, 0, 0).Op(vm.POP).Bytes(),
|
||||||
code: []byte{
|
|
||||||
// outsize, outoffset, insize, inoffset
|
|
||||||
byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0,
|
|
||||||
byte(vm.PUSH1), 0xee, //address
|
|
||||||
byte(vm.GAS), // gas
|
|
||||||
byte(vm.DELEGATECALL),
|
|
||||||
byte(vm.POP),
|
|
||||||
},
|
|
||||||
results: []string{`"1,1,981799,6,12"`, `"1,1,981799,6,0"`},
|
results: []string{`"1,1,981799,6,12"`, `"1,1,981799,6,0"`},
|
||||||
},
|
},
|
||||||
{
|
{ // CALL self-destructing contract
|
||||||
// CALL self-destructing contract
|
code: program.New().Call(nil, 0xff, 0, 0, 0, 0, 0).Op(vm.POP).Bytes(),
|
||||||
code: []byte{
|
|
||||||
// outsize, outoffset, insize, inoffset
|
|
||||||
byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0,
|
|
||||||
byte(vm.PUSH1), 0, // value
|
|
||||||
byte(vm.PUSH1), 0xff, //address
|
|
||||||
byte(vm.GAS), // gas
|
|
||||||
byte(vm.CALL),
|
|
||||||
byte(vm.POP),
|
|
||||||
},
|
|
||||||
results: []string{`"2,2,0,5003,12"`, `"2,2,0,5003,0"`},
|
results: []string{`"2,2,0,5003,12"`, `"2,2,0,5003,0"`},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -896,16 +841,8 @@ func TestJSTracerCreateTx(t *testing.T) {
|
||||||
|
|
||||||
func BenchmarkTracerStepVsCallFrame(b *testing.B) {
|
func BenchmarkTracerStepVsCallFrame(b *testing.B) {
|
||||||
// Simply pushes and pops some values in a loop
|
// Simply pushes and pops some values in a loop
|
||||||
code := []byte{
|
p, lbl := program.New().Jumpdest()
|
||||||
byte(vm.JUMPDEST),
|
code := p.Push(0).Push(0).Ops(vm.POP, vm.POP).Jump(lbl).Bytes()
|
||||||
byte(vm.PUSH1), 0,
|
|
||||||
byte(vm.PUSH1), 0,
|
|
||||||
byte(vm.POP),
|
|
||||||
byte(vm.POP),
|
|
||||||
byte(vm.PUSH1), 0, // jumpdestination
|
|
||||||
byte(vm.JUMP),
|
|
||||||
}
|
|
||||||
|
|
||||||
stepTracer := `
|
stepTracer := `
|
||||||
{
|
{
|
||||||
step: function() {},
|
step: function() {},
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue