Skip to content

Commit c495cd6

Browse files
author
Junghyun Colin Kim
committed
Apply go-ethereum#18318
To tracing CREATE2 instruction, ethereum/go-ethereum@e8ff318 is applied. ethereum/go-ethereum#18318
1 parent ea8a75d commit c495cd6

File tree

6 files changed

+115
-29
lines changed

6 files changed

+115
-29
lines changed

node/cn/tracers/internal/tracers/assets.go

+2-25
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

node/cn/tracers/internal/tracers/call_tracer.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
var op = log.op.toString();
5454
}
5555
// If a new contract is being created, add to the call stack
56-
if (syscall && op == 'CREATE') {
56+
if (syscall && (op == 'CREATE' || op == 'CREATE2')) {
5757
var inOff = log.stack.peek(1).valueOf();
5858
var inEnd = inOff + log.stack.peek(2).valueOf();
5959

@@ -142,7 +142,7 @@
142142
// Pop off the last call and get the execution results
143143
var call = this.callstack.pop();
144144

145-
if (call.type == 'CREATE') {
145+
if (call.type == 'CREATE' || call.type == 'CREATE2') {
146146
// If the call was a CREATE, retrieve the contract address and output code
147147
call.gasUsed = '0x' + bigInt(call.gasIn - call.gasCost - log.getGas()).toString(16);
148148
delete call.gasIn; delete call.gasCost;

node/cn/tracers/internal/tracers/prestate_tracer.js

+8
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@
8989
var from = log.contract.getAddress();
9090
this.lookupAccount(toContract(from, db.getNonce(from)), db);
9191
break;
92+
case "CREATE2":
93+
var from = log.contract.getAddress();
94+
// stack: salt, size, offset, endowment
95+
var offset = log.stack.peek(1).valueOf();
96+
var size = log.stack.peek(2).valueOf();
97+
var end = offset + size;
98+
this.lookupAccount(toContract2(from, log.stack.peek(3).toString(16), log.memory.slice(offset, end)), db);
99+
break;
92100
case "CALL": case "CALLCODE": case "DELEGATECALL": case "STATICCALL":
93101
this.lookupAccount(toAddress(log.stack.peek(1).toString(16)), db);
94102
break;

node/cn/tracers/internal/tracers/tracers.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
// You should have received a copy of the GNU Lesser General Public License
1515
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
1616

17-
//go:generate go-bindata -nometadata -o assets.go -pkg tracers -ignore ((tracers)|(assets)).go ./...
17+
//go:generate go-bindata -nometadata -o assets.go -pkg tracers -ignore tracers.go -ignore assets.go ./...
1818
//go:generate gofmt -s -w assets.go
1919

2020
// Package tracers contains the actual JavaScript tracer assets.

node/cn/tracers/tracer.go

+22
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,28 @@ func New(code string) (*Tracer, error) {
372372
copy(makeSlice(ctx.PushFixedBuffer(20), 20), contract[:])
373373
return 1
374374
})
375+
tracer.vm.PushGlobalGoFunction("toContract2", func(ctx *duktape.Context) int {
376+
var from common.Address
377+
if ptr, size := ctx.GetBuffer(-3); ptr != nil {
378+
from = common.BytesToAddress(makeSlice(ptr, size))
379+
} else {
380+
from = common.HexToAddress(ctx.GetString(-3))
381+
}
382+
// Retrieve salt hex string from js stack
383+
salt := common.HexToHash(ctx.GetString(-2))
384+
// Retrieve code slice from js stack
385+
var code []byte
386+
if ptr, size := ctx.GetBuffer(-1); ptr != nil {
387+
code = common.CopyBytes(makeSlice(ptr, size))
388+
} else {
389+
code = common.FromHex(ctx.GetString(-1))
390+
}
391+
codeHash := crypto.Keccak256(code)
392+
ctx.Pop3()
393+
contract := crypto.CreateAddress2(from, salt, codeHash)
394+
copy(makeSlice(ctx.PushFixedBuffer(20), 20), contract[:])
395+
return 1
396+
})
375397
tracer.vm.PushGlobalGoFunction("isPrecompiled", func(ctx *duktape.Context) int {
376398
_, ok := vm.PrecompiledContractsCypress[common.BytesToAddress(popSlice(ctx))]
377399
ctx.PushBoolean(ok)

node/cn/tracers/tracers_test.go

+80-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
package tracers
2222

2323
import (
24+
"crypto/ecdsa"
25+
"crypto/rand"
2426
"encoding/json"
2527
"github.com/klaytn/klaytn/blockchain"
2628
"github.com/klaytn/klaytn/blockchain/types"
@@ -29,6 +31,7 @@ import (
2931
"github.com/klaytn/klaytn/common/hexutil"
3032
"github.com/klaytn/klaytn/common/math"
3133
"github.com/klaytn/klaytn/crypto"
34+
"github.com/klaytn/klaytn/params"
3235
"github.com/klaytn/klaytn/ser/rlp"
3336
"github.com/klaytn/klaytn/storage/database"
3437
"github.com/klaytn/klaytn/tests"
@@ -126,6 +129,82 @@ type callTracerTest struct {
126129
Result *callTrace `json:"result"`
127130
}
128131

132+
func TestPrestateTracerCreate2(t *testing.T) {
133+
unsigned_tx := types.NewTransaction(1, common.HexToAddress("0x00000000000000000000000000000000deadbeef"),
134+
new(big.Int), 5000000, big.NewInt(1), []byte{})
135+
136+
privateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), rand.Reader)
137+
if err != nil {
138+
t.Fatalf("err %v", err)
139+
}
140+
signer := types.NewEIP155Signer(big.NewInt(1))
141+
tx, err := types.SignTx(unsigned_tx, signer, privateKeyECDSA)
142+
if err != nil {
143+
t.Fatalf("err %v", err)
144+
}
145+
/**
146+
This comes from one of the test-vectors on the Skinny Create2 - EIP
147+
address 0x00000000000000000000000000000000deadbeef
148+
salt 0x00000000000000000000000000000000000000000000000000000000cafebabe
149+
init_code 0xdeadbeef
150+
gas (assuming no mem expansion): 32006
151+
result: 0x60f3f640a8508fC6a86d45DF051962668E1e8AC7
152+
*/
153+
origin, _ := signer.Sender(tx)
154+
context := vm.Context{
155+
CanTransfer: blockchain.CanTransfer,
156+
Transfer: blockchain.Transfer,
157+
Origin: origin,
158+
Coinbase: common.Address{},
159+
BlockNumber: new(big.Int).SetUint64(8000000),
160+
Time: new(big.Int).SetUint64(5),
161+
BlockScore: big.NewInt(0x30000),
162+
GasLimit: uint64(6000000),
163+
GasPrice: big.NewInt(1),
164+
}
165+
alloc := blockchain.GenesisAlloc{}
166+
// The code pushes 'deadbeef' into memory, then the other params, and calls CREATE2, then returns
167+
// the address
168+
alloc[common.HexToAddress("0x00000000000000000000000000000000deadbeef")] = blockchain.GenesisAccount{
169+
Nonce: 1,
170+
Code: hexutil.MustDecode("0x63deadbeef60005263cafebabe6004601c6000F560005260206000F3"),
171+
Balance: big.NewInt(1),
172+
}
173+
alloc[origin] = blockchain.GenesisAccount{
174+
Nonce: 1,
175+
Code: []byte{},
176+
Balance: big.NewInt(500000000000000),
177+
}
178+
statedb := tests.MakePreState(database.NewMemoryDBManager(), alloc)
179+
// Create the tracer, the EVM environment and run it
180+
tracer, err := New("prestateTracer")
181+
if err != nil {
182+
t.Fatalf("failed to create call tracer: %v", err)
183+
}
184+
evm := vm.NewEVM(context, statedb, params.MainnetChainConfig, &vm.Config{Debug: true, Tracer: tracer})
185+
186+
msg, err := tx.AsMessageWithAccountKeyPicker(signer, statedb, context.BlockNumber.Uint64())
187+
if err != nil {
188+
t.Fatalf("failed to prepare transaction for tracing: %v", err)
189+
}
190+
st := blockchain.NewStateTransition(evm, msg)
191+
if _, _, kerr := st.TransitionDb(); kerr.ErrTxInvalid != nil {
192+
t.Fatalf("failed to execute transaction: %v", kerr.ErrTxInvalid)
193+
}
194+
// Retrieve the trace result and compare against the etalon
195+
res, err := tracer.GetResult()
196+
if err != nil {
197+
t.Fatalf("failed to retrieve trace result: %v", err)
198+
}
199+
ret := make(map[string]interface{})
200+
if err := json.Unmarshal(res, &ret); err != nil {
201+
t.Fatalf("failed to unmarshal trace result: %v", err)
202+
}
203+
if _, has := ret["0x60f3f640a8508fc6a86d45df051962668e1e8ac7"]; !has {
204+
t.Fatalf("Expected 0x60f3f640a8508fc6a86d45df051962668e1e8ac7 in result")
205+
}
206+
}
207+
129208
// Iterates over all the input-output datasets in the tracer test harness and
130209
// runs the JavaScript tracers against them.
131210
func TestCallTracer(t *testing.T) {
@@ -221,7 +300,7 @@ func TestCallTracer(t *testing.T) {
221300
t.Fatalf("failed to unmarshal trace result: %v", err)
222301
}
223302
if !reflect.DeepEqual(ret, test.Result) {
224-
t.Fatalf("trace mismatch: have %+v, want %+v", ret, test.Result)
303+
t.Fatalf("trace mismatch: \nhave %+v, \nwant %+v", ret, test.Result)
225304
}
226305
})
227306
}

0 commit comments

Comments
 (0)