mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 15:16:43 +00:00
Added greater support for SetCode transactions
This commit is contained in:
parent
dbe1dac352
commit
b20db144a2
12 changed files with 1067 additions and 3647 deletions
|
|
@ -1,6 +0,0 @@
|
||||||
version: v1
|
|
||||||
plugins:
|
|
||||||
- plugin: buf.build/protocolbuffers/go:v1.31.0
|
|
||||||
out: pb
|
|
||||||
opt: paths=source_relative
|
|
||||||
|
|
||||||
|
|
@ -29,9 +29,9 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/internal/version"
|
"github.com/ethereum/go-ethereum/internal/version"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
pbeth "github.com/ethereum/go-ethereum/pb/sf/ethereum/type/v2"
|
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
|
pbeth "github.com/streamingfast/firehose-ethereum/types/pb/sf/ethereum/type/v2"
|
||||||
"golang.org/x/exp/maps"
|
"golang.org/x/exp/maps"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
"google.golang.org/protobuf/types/known/timestamppb"
|
"google.golang.org/protobuf/types/known/timestamppb"
|
||||||
|
|
@ -158,6 +158,7 @@ type Firehose struct {
|
||||||
blockReorderOrdinal bool
|
blockReorderOrdinal bool
|
||||||
blockReorderOrdinalSnapshot uint64
|
blockReorderOrdinalSnapshot uint64
|
||||||
blockReorderOrdinalOnce sync.Once
|
blockReorderOrdinalOnce sync.Once
|
||||||
|
blockIsGenesis bool
|
||||||
|
|
||||||
// Transaction state
|
// Transaction state
|
||||||
evm *tracing.VMContext
|
evm *tracing.VMContext
|
||||||
|
|
@ -279,6 +280,7 @@ func (f *Firehose) resetBlock() {
|
||||||
f.blockReorderOrdinal = false
|
f.blockReorderOrdinal = false
|
||||||
f.blockReorderOrdinalSnapshot = 0
|
f.blockReorderOrdinalSnapshot = 0
|
||||||
f.blockReorderOrdinalOnce = sync.Once{}
|
f.blockReorderOrdinalOnce = sync.Once{}
|
||||||
|
f.blockIsGenesis = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// resetTransaction resets the transaction state and the call state in one shot
|
// resetTransaction resets the transaction state and the call state in one shot
|
||||||
|
|
@ -536,7 +538,7 @@ func (f *Firehose) OnSystemCallEnd() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Firehose) OnTxStart(evm *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
func (f *Firehose) OnTxStart(evm *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
||||||
firehoseInfo("trx start (tracer=%s hash=%s type=%d gas=%d isolated=%t input=%s)", f.tracerID, tx.Hash(), tx.Type(), tx.Gas(), f.transactionIsolated, inputView(tx.Data()))
|
firehoseInfo("trx start (tracer=%s hash=%s %s type=%d gas=%d isolated=%t input=%s)", f.tracerID, tx.Hash(), fromToTxView(&from, tx), tx.Type(), tx.Gas(), f.transactionIsolated, inputView(tx.Data()))
|
||||||
|
|
||||||
f.ensureInBlockAndNotInTrxAndNotInCall()
|
f.ensureInBlockAndNotInTrxAndNotInCall()
|
||||||
|
|
||||||
|
|
@ -557,12 +559,7 @@ func (f *Firehose) OnTxStart(evm *tracing.VMContext, tx *types.Transaction, from
|
||||||
func (f *Firehose) onTxStart(tx *types.Transaction, hash common.Hash, from, to common.Address) {
|
func (f *Firehose) onTxStart(tx *types.Transaction, hash common.Hash, from, to common.Address) {
|
||||||
v, r, s := tx.RawSignatureValues()
|
v, r, s := tx.RawSignatureValues()
|
||||||
|
|
||||||
var blobGas *uint64
|
trx := &pbeth.TransactionTrace{
|
||||||
if tx.Type() == types.BlobTxType {
|
|
||||||
blobGas = ptr(tx.BlobGas())
|
|
||||||
}
|
|
||||||
|
|
||||||
f.transaction = &pbeth.TransactionTrace{
|
|
||||||
BeginOrdinal: f.blockOrdinal.Next(),
|
BeginOrdinal: f.blockOrdinal.Next(),
|
||||||
Hash: hash.Bytes(),
|
Hash: hash.Bytes(),
|
||||||
From: from.Bytes(),
|
From: from.Bytes(),
|
||||||
|
|
@ -579,14 +576,23 @@ func (f *Firehose) onTxStart(tx *types.Transaction, hash common.Hash, from, to c
|
||||||
AccessList: newAccessListFromChain(tx.AccessList()),
|
AccessList: newAccessListFromChain(tx.AccessList()),
|
||||||
MaxFeePerGas: maxFeePerGas(tx),
|
MaxFeePerGas: maxFeePerGas(tx),
|
||||||
MaxPriorityFeePerGas: maxPriorityFeePerGas(tx),
|
MaxPriorityFeePerGas: maxPriorityFeePerGas(tx),
|
||||||
BlobGas: blobGas,
|
|
||||||
BlobGasFeeCap: firehoseBigIntFromNative(tx.BlobGasFeeCap()),
|
|
||||||
BlobHashes: newBlobHashesFromChain(tx.BlobHashes()),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch tx.Type() {
|
||||||
|
case types.BlobTxType:
|
||||||
|
trx.BlobGas = ptr(tx.BlobGas())
|
||||||
|
trx.BlobGasFeeCap = firehoseBigIntFromNative(tx.BlobGasFeeCap())
|
||||||
|
trx.BlobHashes = newBlobHashesFromChain(tx.BlobHashes())
|
||||||
|
|
||||||
|
case types.SetCodeTxType:
|
||||||
|
trx.SetCodeAuthorizations = newSetCodeAuthorizationsFromChain(tx.SetCodeAuthorizations())
|
||||||
|
}
|
||||||
|
|
||||||
|
f.transaction = trx
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Firehose) OnTxEnd(receipt *types.Receipt, err error) {
|
func (f *Firehose) OnTxEnd(receipt *types.Receipt, err error) {
|
||||||
firehoseInfo("trx ending (tracer=%s, isolated=%t, error=%s)", f.tracerID, f.transactionIsolated, errorView(err))
|
firehoseInfo("trx ending (tracer=%s, isolated=%t, err=%s)", f.tracerID, f.transactionIsolated, errorView(err))
|
||||||
f.ensureInBlockAndInTrx()
|
f.ensureInBlockAndInTrx()
|
||||||
|
|
||||||
trxTrace := f.completeTransaction(receipt)
|
trxTrace := f.completeTransaction(receipt)
|
||||||
|
|
@ -613,7 +619,7 @@ func (f *Firehose) OnTxEnd(receipt *types.Receipt, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Firehose) completeTransaction(receipt *types.Receipt) *pbeth.TransactionTrace {
|
func (f *Firehose) completeTransaction(receipt *types.Receipt) *pbeth.TransactionTrace {
|
||||||
firehoseInfo("completing transaction (call_count=%d receipt=%s)", len(f.transaction.Calls), (*receiptView)(receipt))
|
firehoseInfo("completing transaction (call_count=%d receipt=%s)", len(f.transaction.Calls), receiptView(receipt))
|
||||||
|
|
||||||
// Sorting needs to happen first, before we populate the state reverted
|
// Sorting needs to happen first, before we populate the state reverted
|
||||||
slices.SortFunc(f.transaction.Calls, func(i, j *pbeth.Call) int {
|
slices.SortFunc(f.transaction.Calls, func(i, j *pbeth.Call) int {
|
||||||
|
|
@ -622,6 +628,10 @@ func (f *Firehose) completeTransaction(receipt *types.Receipt) *pbeth.Transactio
|
||||||
|
|
||||||
rootCall := f.transaction.Calls[0]
|
rootCall := f.transaction.Calls[0]
|
||||||
|
|
||||||
|
// Can be done prior moving last deferred call state to the root call as we are only interested from the initial
|
||||||
|
// deferred state that already been transferred into the root call (in `onCallStart(...)`).
|
||||||
|
f.discardUncommittedSetCodeAuthorization(rootCall)
|
||||||
|
|
||||||
if !f.deferredCallState.IsEmpty() {
|
if !f.deferredCallState.IsEmpty() {
|
||||||
f.deferredCallState.MaybePopulateCallAndReset("root", rootCall)
|
f.deferredCallState.MaybePopulateCallAndReset("root", rootCall)
|
||||||
}
|
}
|
||||||
|
|
@ -686,6 +696,39 @@ func (f *Firehose) populateStateReverted() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// discardUncommittedSetCodeAuthorization set `discarded = true` for all the SetCodeAuthorization element
|
||||||
|
// that don't have a corresponding NonceChange coming from the root call of the transaction, which
|
||||||
|
// means they weren't committed to the state.
|
||||||
|
//
|
||||||
|
// Indeed, EIP-7702 states that are invalid SetCodeAuthorization is simply discard and it's not recorded
|
||||||
|
// to chain's state.
|
||||||
|
func (f *Firehose) discardUncommittedSetCodeAuthorization(rootCall *pbeth.Call) {
|
||||||
|
usedNonceChange := map[int]bool{}
|
||||||
|
findNonceChange := func(forAddress []byte, nonce uint64) *pbeth.NonceChange {
|
||||||
|
for i, change := range rootCall.NonceChanges {
|
||||||
|
if change.OldValue == nonce && change.NewValue == nonce+1 && bytes.Equal(change.Address, forAddress) && usedNonceChange[i] == false {
|
||||||
|
usedNonceChange[i] = true
|
||||||
|
return change
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, auth := range f.transaction.SetCodeAuthorizations {
|
||||||
|
if len(auth.Authority) == 0 {
|
||||||
|
// Nothing to check, authority is empty, it's not a valid authorization
|
||||||
|
auth.Discarded = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if findNonceChange(auth.Authority, auth.Nonce) == nil {
|
||||||
|
firehoseDebug("discarded set code authorization, no corresponding nonce change found (address=%s nonce=%d)", hex.EncodeToString(auth.Authority), auth.Nonce)
|
||||||
|
auth.Discarded = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (f *Firehose) removeLogBlockIndexOnStateRevertedCalls() {
|
func (f *Firehose) removeLogBlockIndexOnStateRevertedCalls() {
|
||||||
for _, call := range f.transaction.Calls {
|
for _, call := range f.transaction.Calls {
|
||||||
if call.StateReverted {
|
if call.StateReverted {
|
||||||
|
|
@ -995,7 +1038,7 @@ func (f *Firehose) captureInterpreterStep(activeCall *pbeth.Call, pc uint64, op
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Firehose) callStart(source string, callType pbeth.CallType, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
func (f *Firehose) callStart(source string, callType pbeth.CallType, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
||||||
firehoseDebug("call start (source=%s index=%d type=%s input=%s)", source, f.callStack.NextIndex(), callType, inputView(input))
|
firehoseDebug("call start (source=%s index=%d type=%s ref=%s input=%s)", source, f.callStack.NextIndex(), callType, fromToView(&from, &to), inputView(input))
|
||||||
f.ensureInBlockAndInTrx()
|
f.ensureInBlockAndInTrx()
|
||||||
|
|
||||||
if *f.applyBackwardCompatibility {
|
if *f.applyBackwardCompatibility {
|
||||||
|
|
@ -1018,6 +1061,18 @@ func (f *Firehose) callStart(source string, callType pbeth.CallType, from common
|
||||||
GasLimit: gas,
|
GasLimit: gas,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if f.blockRules.IsPrague && !f.inSystemCall && !f.blockIsGenesis && callType != pbeth.CallType_CREATE {
|
||||||
|
firehoseTrace("call resolving delegation (from=%s)", from)
|
||||||
|
|
||||||
|
code := f.evm.StateDB.GetCode(to)
|
||||||
|
if len(code) != 0 {
|
||||||
|
if target, ok := types.ParseDelegation(code); ok {
|
||||||
|
firehoseDebug("call resolved delegation (from=%s, delegates_to=%s)", from, target)
|
||||||
|
call.AddressDelegatesTo = target.Bytes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if *f.applyBackwardCompatibility {
|
if *f.applyBackwardCompatibility {
|
||||||
// Known Firehose issue: The BeginOrdinal of the genesis block root call is never actually
|
// Known Firehose issue: The BeginOrdinal of the genesis block root call is never actually
|
||||||
// incremented and it's always 0.
|
// incremented and it's always 0.
|
||||||
|
|
@ -1174,6 +1229,9 @@ func (f *Firehose) OnGenesisBlock(b *types.Block, alloc types.GenesisAlloc) {
|
||||||
|
|
||||||
f.ensureBlockChainInit()
|
f.ensureBlockChainInit()
|
||||||
|
|
||||||
|
// Going to be reset in OnBlockEnd
|
||||||
|
f.blockIsGenesis = true
|
||||||
|
|
||||||
f.OnBlockStart(tracing.BlockEvent{Block: b, Finalized: nil, Safe: nil})
|
f.OnBlockStart(tracing.BlockEvent{Block: b, Finalized: nil, Safe: nil})
|
||||||
f.onTxStart(types.NewTx(&types.LegacyTx{}), emptyCommonHash, emptyCommonAddress, emptyCommonAddress)
|
f.onTxStart(types.NewTx(&types.LegacyTx{}), emptyCommonHash, emptyCommonAddress, emptyCommonAddress)
|
||||||
f.OnCallEnter(0, byte(vm.CALL), emptyCommonAddress, emptyCommonAddress, nil, 0, nil)
|
f.OnCallEnter(0, byte(vm.CALL), emptyCommonAddress, emptyCommonAddress, nil, 0, nil)
|
||||||
|
|
@ -1260,7 +1318,7 @@ func (f *Firehose) OnBalanceChange(a common.Address, prev, new *big.Int, reason
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Firehose) newBalanceChange(tag string, address common.Address, oldValue, newValue *big.Int, reason pbeth.BalanceChange_Reason) *pbeth.BalanceChange {
|
func (f *Firehose) newBalanceChange(tag string, address common.Address, oldValue, newValue *big.Int, reason pbeth.BalanceChange_Reason) *pbeth.BalanceChange {
|
||||||
firehoseTrace("balance changed (tag=%s before=%d after=%d reason=%s)", tag, oldValue, newValue, reason)
|
firehoseTrace("balance changed (tag=%s address=%s before=%d after=%d reason=%s)", tag, shortAddressView(&address), oldValue, newValue, reason)
|
||||||
|
|
||||||
if reason == pbeth.BalanceChange_REASON_UNKNOWN {
|
if reason == pbeth.BalanceChange_REASON_UNKNOWN {
|
||||||
panic(fmt.Errorf("received unknown balance change reason %s", reason))
|
panic(fmt.Errorf("received unknown balance change reason %s", reason))
|
||||||
|
|
@ -1302,8 +1360,14 @@ func (f *Firehose) OnCodeChange(a common.Address, prevCodeHash common.Hash, prev
|
||||||
|
|
||||||
if f.transaction != nil {
|
if f.transaction != nil {
|
||||||
activeCall := f.callStack.Peek()
|
activeCall := f.callStack.Peek()
|
||||||
|
|
||||||
|
// Since EIP-7702 and the introduction of the `SetCode` transaction, a traced `StateDB.SetCode(...)` call
|
||||||
|
// is now happening within the "bootstrap" transaction phase which happens before any call is made. So
|
||||||
|
// in the event there is no active call, we push the code change to the deferred state and will be applied
|
||||||
|
// on the root call when it's finally created.
|
||||||
if activeCall == nil {
|
if activeCall == nil {
|
||||||
f.panicInvalidState("caller expected to be in call state but we were not, this is a bug", 0)
|
f.deferredCallState.codeChanges = append(f.deferredCallState.codeChanges, f.newCodeChange(a, prevCodeHash, prev, codeHash, code))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Geth 1.14.12 introduced a new behavior where a code change is emitted when a contract
|
// Geth 1.14.12 introduced a new behavior where a code change is emitted when a contract
|
||||||
|
|
@ -1325,28 +1389,25 @@ func (f *Firehose) OnCodeChange(a common.Address, prevCodeHash common.Hash, prev
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
activeCall.CodeChanges = append(activeCall.CodeChanges, &pbeth.CodeChange{
|
activeCall.CodeChanges = append(activeCall.CodeChanges, f.newCodeChange(a, prevCodeHash, prev, codeHash, code))
|
||||||
Address: a.Bytes(),
|
|
||||||
OldHash: prevCodeHash.Bytes(),
|
|
||||||
OldCode: prev,
|
|
||||||
NewHash: codeHash.Bytes(),
|
|
||||||
NewCode: code,
|
|
||||||
Ordinal: f.blockOrdinal.Next(),
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
f.block.CodeChanges = append(f.block.CodeChanges, &pbeth.CodeChange{
|
f.block.CodeChanges = append(f.block.CodeChanges, f.newCodeChange(a, prevCodeHash, prev, codeHash, code))
|
||||||
Address: a.Bytes(),
|
}
|
||||||
OldHash: prevCodeHash.Bytes(),
|
}
|
||||||
OldCode: prev,
|
|
||||||
NewHash: codeHash.Bytes(),
|
func (f *Firehose) newCodeChange(addr common.Address, prevCodeHash common.Hash, prev []byte, codeHash common.Hash, code []byte) *pbeth.CodeChange {
|
||||||
NewCode: code,
|
return &pbeth.CodeChange{
|
||||||
Ordinal: f.blockOrdinal.Next(),
|
Address: addr.Bytes(),
|
||||||
})
|
OldHash: prevCodeHash.Bytes(),
|
||||||
|
OldCode: prev,
|
||||||
|
NewHash: codeHash.Bytes(),
|
||||||
|
NewCode: code,
|
||||||
|
Ordinal: f.blockOrdinal.Next(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Firehose) OnStorageChange(a common.Address, k, prev, new common.Hash) {
|
func (f *Firehose) OnStorageChange(a common.Address, k, prev, new common.Hash) {
|
||||||
firehoseTrace("storage changed (key=%s, before=%s after=%s)", k, prev, new)
|
firehoseTrace("storage changed (address=%s key=%s, before=%s after=%s)", shortAddressView(&a), k, prev, new)
|
||||||
|
|
||||||
f.ensureInBlockAndInTrxAndInCall()
|
f.ensureInBlockAndInTrxAndInCall()
|
||||||
|
|
||||||
|
|
@ -1609,7 +1670,7 @@ func (f *Firehose) printBlockToFirehose(block *pbeth.Block, finalityStatus *Fina
|
||||||
}
|
}
|
||||||
|
|
||||||
// **Important* The final space in the Sprintf template is mandatory!
|
// **Important* The final space in the Sprintf template is mandatory!
|
||||||
f.outputBuffer.WriteString(fmt.Sprintf("FIRE BLOCK %d %s %d %s %d %d ", block.Number, hex.EncodeToString(block.Hash), previousNum, previousHash, libNum, block.Time().UnixNano()))
|
f.outputBuffer.WriteString(fmt.Sprintf("FIRE BLOCK %d %s %d %s %d %d ", block.Number, hex.EncodeToString(block.Hash), previousNum, previousHash, libNum, block.MustTime().UnixNano()))
|
||||||
|
|
||||||
encoder := base64.NewEncoder(base64.StdEncoding, f.outputBuffer)
|
encoder := base64.NewEncoder(base64.StdEncoding, f.outputBuffer)
|
||||||
if _, err = encoder.Write(marshalled); err != nil {
|
if _, err = encoder.Write(marshalled); err != nil {
|
||||||
|
|
@ -1860,6 +1921,37 @@ func newBlobHashesFromChain(blobHashes []common.Hash) (out [][]byte) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newSetCodeAuthorizationsFromChain(authorizations []types.SetCodeAuthorization) (out []*pbeth.SetCodeAuthorization) {
|
||||||
|
if len(authorizations) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
out = make([]*pbeth.SetCodeAuthorization, len(authorizations))
|
||||||
|
for i, authorization := range authorizations {
|
||||||
|
pbAuthorization := &pbeth.SetCodeAuthorization{
|
||||||
|
ChainId: authorization.ChainID.Bytes(),
|
||||||
|
Nonce: authorization.Nonce,
|
||||||
|
V: uint32(authorization.V),
|
||||||
|
R: normalizeSignaturePoint(authorization.R.Bytes()),
|
||||||
|
S: normalizeSignaturePoint(authorization.S.Bytes()),
|
||||||
|
}
|
||||||
|
|
||||||
|
authority, err := authorization.Authority()
|
||||||
|
if err != nil {
|
||||||
|
// The node skips invalid authorizations, we do the same, at transaction's end, we will
|
||||||
|
// also remove authorizations that didn't result into a code change.
|
||||||
|
firehoseDebug("failed to compute authority for authorization at index %d (err=%s)", i, errorView(err))
|
||||||
|
pbAuthorization.Discarded = true
|
||||||
|
} else {
|
||||||
|
pbAuthorization.Authority = authority.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
out[i] = pbAuthorization
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var balanceChangeReasonToPb = map[tracing.BalanceChangeReason]pbeth.BalanceChange_Reason{
|
var balanceChangeReasonToPb = map[tracing.BalanceChangeReason]pbeth.BalanceChange_Reason{
|
||||||
tracing.BalanceIncreaseRewardMineUncle: pbeth.BalanceChange_REASON_REWARD_MINE_UNCLE,
|
tracing.BalanceIncreaseRewardMineUncle: pbeth.BalanceChange_REASON_REWARD_MINE_UNCLE,
|
||||||
tracing.BalanceIncreaseRewardMineBlock: pbeth.BalanceChange_REASON_REWARD_MINE_BLOCK,
|
tracing.BalanceIncreaseRewardMineBlock: pbeth.BalanceChange_REASON_REWARD_MINE_BLOCK,
|
||||||
|
|
@ -2113,6 +2205,7 @@ type DeferredCallState struct {
|
||||||
balanceChanges []*pbeth.BalanceChange
|
balanceChanges []*pbeth.BalanceChange
|
||||||
gasChanges []*pbeth.GasChange
|
gasChanges []*pbeth.GasChange
|
||||||
nonceChanges []*pbeth.NonceChange
|
nonceChanges []*pbeth.NonceChange
|
||||||
|
codeChanges []*pbeth.CodeChange
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDeferredCallState() *DeferredCallState {
|
func NewDeferredCallState() *DeferredCallState {
|
||||||
|
|
@ -2133,6 +2226,7 @@ func (d *DeferredCallState) MaybePopulateCallAndReset(source string, call *pbeth
|
||||||
call.BalanceChanges = append(call.BalanceChanges, d.balanceChanges...)
|
call.BalanceChanges = append(call.BalanceChanges, d.balanceChanges...)
|
||||||
call.GasChanges = append(call.GasChanges, d.gasChanges...)
|
call.GasChanges = append(call.GasChanges, d.gasChanges...)
|
||||||
call.NonceChanges = append(call.NonceChanges, d.nonceChanges...)
|
call.NonceChanges = append(call.NonceChanges, d.nonceChanges...)
|
||||||
|
call.CodeChanges = append(call.CodeChanges, d.codeChanges...)
|
||||||
|
|
||||||
d.Reset()
|
d.Reset()
|
||||||
|
|
||||||
|
|
@ -2140,7 +2234,7 @@ func (d *DeferredCallState) MaybePopulateCallAndReset(source string, call *pbeth
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DeferredCallState) IsEmpty() bool {
|
func (d *DeferredCallState) IsEmpty() bool {
|
||||||
return len(d.accountCreations) == 0 && len(d.balanceChanges) == 0 && len(d.gasChanges) == 0 && len(d.nonceChanges) == 0
|
return len(d.accountCreations) == 0 && len(d.balanceChanges) == 0 && len(d.gasChanges) == 0 && len(d.nonceChanges) == 0 && len(d.codeChanges) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DeferredCallState) Reset() {
|
func (d *DeferredCallState) Reset() {
|
||||||
|
|
@ -2148,8 +2242,10 @@ func (d *DeferredCallState) Reset() {
|
||||||
d.balanceChanges = nil
|
d.balanceChanges = nil
|
||||||
d.gasChanges = nil
|
d.gasChanges = nil
|
||||||
d.nonceChanges = nil
|
d.nonceChanges = nil
|
||||||
|
d.codeChanges = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:inline
|
||||||
func errorView(err error) _errorView {
|
func errorView(err error) _errorView {
|
||||||
return _errorView{err}
|
return _errorView{err}
|
||||||
}
|
}
|
||||||
|
|
@ -2163,7 +2259,57 @@ func (e _errorView) String() string {
|
||||||
return "<no error>"
|
return "<no error>"
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.err.Error()
|
return `"` + e.err.Error() + `"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:inline
|
||||||
|
func fromToTxView(from *common.Address, tx *types.Transaction) _fromToView {
|
||||||
|
return _fromToView{from, tx.To()}
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:inline
|
||||||
|
func fromToView(from *common.Address, to *common.Address) _fromToView {
|
||||||
|
return _fromToView{from, to}
|
||||||
|
}
|
||||||
|
|
||||||
|
type _fromToView struct {
|
||||||
|
// from is actually always set
|
||||||
|
from *common.Address
|
||||||
|
to *common.Address
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b _fromToView) String() string {
|
||||||
|
if b.from == nil && b.to == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
to := "<contract>"
|
||||||
|
if b.to != nil {
|
||||||
|
to = shortenAddress(b.to)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("(%s -> %s)", shortenAddress(b.from), to)
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:inline
|
||||||
|
func shortAddressView(addr *common.Address) *_shortAddressView {
|
||||||
|
return (*_shortAddressView)(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
type _shortAddressView common.Address
|
||||||
|
|
||||||
|
func (a *_shortAddressView) String() string {
|
||||||
|
if a == nil {
|
||||||
|
return "<nil>"
|
||||||
|
}
|
||||||
|
|
||||||
|
return shortenAddress((*common.Address)(a))
|
||||||
|
}
|
||||||
|
|
||||||
|
func shortenAddress(addr *common.Address) string {
|
||||||
|
full := addr.String()
|
||||||
|
|
||||||
|
return full[:6] + ".." + full[len(full)-4:]
|
||||||
}
|
}
|
||||||
|
|
||||||
type inputView []byte
|
type inputView []byte
|
||||||
|
|
@ -2199,9 +2345,14 @@ func (b outputView) String() string {
|
||||||
return fmt.Sprintf("%d bytes", len(b))
|
return fmt.Sprintf("%d bytes", len(b))
|
||||||
}
|
}
|
||||||
|
|
||||||
type receiptView types.Receipt
|
//go:inline
|
||||||
|
func receiptView(receipt *types.Receipt) *_receiptView {
|
||||||
|
return (*_receiptView)(receipt)
|
||||||
|
}
|
||||||
|
|
||||||
func (r *receiptView) String() string {
|
type _receiptView types.Receipt
|
||||||
|
|
||||||
|
func (r *_receiptView) String() string {
|
||||||
if r == nil {
|
if r == nil {
|
||||||
return "<failed>"
|
return "<failed>"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import (
|
||||||
"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/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
pbeth "github.com/ethereum/go-ethereum/pb/sf/ethereum/type/v2"
|
pbeth "github.com/streamingfast/firehose-ethereum/types/pb/sf/ethereum/type/v2"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"golang.org/x/exp/maps"
|
"golang.org/x/exp/maps"
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,23 @@
|
||||||
package firehose_test
|
package firehose_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/beacon"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"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/eth/tracers"
|
"github.com/ethereum/go-ethereum/core/vm/program"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
|
"github.com/holiman/uint256"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -28,18 +33,10 @@ func TestFirehoseChain(t *testing.T) {
|
||||||
BaseFee: big.NewInt(8),
|
BaseFee: big.NewInt(8),
|
||||||
}
|
}
|
||||||
|
|
||||||
tracer, err := tracers.NewFirehoseFromRawJSON(json.RawMessage(`{
|
tracer, tracingHooks, onClose := newFirehoseTestTracer(t)
|
||||||
"applyBackwardsCompatibility": true,
|
defer onClose()
|
||||||
"_private": {
|
|
||||||
"flushToTestBuffer": true,
|
|
||||||
"ignoreGenesisBlock": true
|
|
||||||
}
|
|
||||||
}`))
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
hooks := tracers.NewTracingHooksFromFirehose(tracer)
|
genesis, blockchain := newBlockchain(t, types.GenesisAlloc{}, context, tracingHooks)
|
||||||
|
|
||||||
genesis, blockchain := newBlockchain(t, types.GenesisAlloc{}, context, hooks)
|
|
||||||
|
|
||||||
block := types.NewBlock(&types.Header{
|
block := types.NewBlock(&types.Header{
|
||||||
ParentHash: genesis.ToBlock().Hash(),
|
ParentHash: genesis.ToBlock().Hash(),
|
||||||
|
|
@ -81,15 +78,10 @@ func TestFirehosePrestate(t *testing.T) {
|
||||||
name := filepath.Base(folder)
|
name := filepath.Base(folder)
|
||||||
|
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
tracer, err := tracers.NewFirehoseFromRawJSON(json.RawMessage(`{
|
tracer, tracingHooks, onClose := newFirehoseTestTracer(t)
|
||||||
"applyBackwardsCompatibility": true,
|
defer onClose()
|
||||||
"_private": {
|
|
||||||
"flushToTestBuffer": true
|
|
||||||
}
|
|
||||||
}`))
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
runPrestateBlock(t, filepath.Join(folder, "prestate.json"), tracers.NewTracingHooksFromFirehose(tracer))
|
runPrestateBlock(t, filepath.Join(folder, "prestate.json"), tracingHooks)
|
||||||
|
|
||||||
genesisLine, blockLines, unknownLines := readTracerFirehoseLines(t, tracer)
|
genesisLine, blockLines, unknownLines := readTracerFirehoseLines(t, tracer)
|
||||||
require.Len(t, unknownLines, 0, "Lines:\n%s", strings.Join(slicesMap(unknownLines, func(l unknownLine) string { return "- '" + string(l) + "'" }), "\n"))
|
require.Len(t, unknownLines, 0, "Lines:\n%s", strings.Join(slicesMap(unknownLines, func(l unknownLine) string { return "- '" + string(l) + "'" }), "\n"))
|
||||||
|
|
@ -99,3 +91,127 @@ func TestFirehosePrestate(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFirehose_EIP7702(t *testing.T) {
|
||||||
|
// Copied from ./core/blockchain_test.go#L4180 (TestEIP7702)
|
||||||
|
|
||||||
|
var (
|
||||||
|
config = *params.MergedTestChainConfig
|
||||||
|
signer = types.LatestSigner(&config)
|
||||||
|
engine = beacon.New(ethash.NewFaker())
|
||||||
|
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
|
key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
|
||||||
|
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
|
||||||
|
addr2 = crypto.PubkeyToAddress(key2.PublicKey)
|
||||||
|
aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa")
|
||||||
|
bb = common.HexToAddress("0x000000000000000000000000000000000000bbbb")
|
||||||
|
cc = common.HexToAddress("0x000000000000000000000000000000000000cccc")
|
||||||
|
funds = new(big.Int).Mul(common.Big1, big.NewInt(params.Ether))
|
||||||
|
)
|
||||||
|
|
||||||
|
gspec := &core.Genesis{
|
||||||
|
Config: &config,
|
||||||
|
Alloc: types.GenesisAlloc{
|
||||||
|
addr1: {Balance: funds},
|
||||||
|
addr2: {Balance: funds},
|
||||||
|
aa: { // The address 0xAAAA calls into addr2
|
||||||
|
Code: program.New().Call(nil, addr2, 1, 0, 0, 0, 0).Bytes(),
|
||||||
|
Nonce: 0,
|
||||||
|
Balance: big.NewInt(0),
|
||||||
|
},
|
||||||
|
bb: { // The address 0xBBBB sstores 42 into slot 42.
|
||||||
|
Code: program.New().Sstore(0x42, 0x42).Bytes(),
|
||||||
|
Nonce: 0,
|
||||||
|
Balance: big.NewInt(0),
|
||||||
|
},
|
||||||
|
cc: { // The address 0xCCCC sstores 42 into slot 42.
|
||||||
|
Code: program.New().Sstore(0x42, 0x42).Bytes(),
|
||||||
|
Nonce: 0,
|
||||||
|
Balance: big.NewInt(0),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign authorization tuples.
|
||||||
|
// The way the auths are combined, it becomes
|
||||||
|
// 1. tx -> addr1 which is delegated to 0xaaaa
|
||||||
|
// 2. addr1:0xaaaa calls into addr2:0xbbbb
|
||||||
|
// 3. addr2:0xbbbb writes to storage
|
||||||
|
auth1, _ := types.SignSetCode(key1, types.SetCodeAuthorization{
|
||||||
|
ChainID: *uint256.MustFromBig(gspec.Config.ChainID),
|
||||||
|
Address: aa,
|
||||||
|
Nonce: 1,
|
||||||
|
})
|
||||||
|
auth2OverwrittenLaterInList, _ := types.SignSetCode(key2, types.SetCodeAuthorization{
|
||||||
|
Address: cc,
|
||||||
|
Nonce: 0,
|
||||||
|
})
|
||||||
|
auth3InvalidAuthority := auth2OverwrittenLaterInList
|
||||||
|
auth3InvalidAuthority.V = 4
|
||||||
|
auth4, _ := types.SignSetCode(key2, types.SetCodeAuthorization{
|
||||||
|
Address: bb,
|
||||||
|
Nonce: 1,
|
||||||
|
})
|
||||||
|
auth5InvalidNonce, _ := types.SignSetCode(key2, types.SetCodeAuthorization{
|
||||||
|
Address: bb,
|
||||||
|
Nonce: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
auth1Reset, _ := types.SignSetCode(key1, types.SetCodeAuthorization{
|
||||||
|
ChainID: *uint256.MustFromBig(gspec.Config.ChainID),
|
||||||
|
Address: common.Address{},
|
||||||
|
Nonce: 4,
|
||||||
|
})
|
||||||
|
|
||||||
|
_, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, 3, func(i int, b *core.BlockGen) {
|
||||||
|
b.SetCoinbase(aa)
|
||||||
|
|
||||||
|
if i == 0 {
|
||||||
|
txdata := &types.SetCodeTx{
|
||||||
|
ChainID: uint256.MustFromBig(gspec.Config.ChainID),
|
||||||
|
Nonce: 0,
|
||||||
|
To: addr1,
|
||||||
|
Gas: 500000,
|
||||||
|
GasFeeCap: uint256.MustFromBig(newGwei(5)),
|
||||||
|
GasTipCap: uint256.NewInt(2),
|
||||||
|
AuthList: []types.SetCodeAuthorization{auth1, auth2OverwrittenLaterInList, auth3InvalidAuthority, auth4, auth5InvalidNonce},
|
||||||
|
}
|
||||||
|
tx := types.MustSignNewTx(key1, signer, txdata)
|
||||||
|
b.AddTx(tx)
|
||||||
|
} else if i == 1 {
|
||||||
|
txdata := &types.LegacyTx{
|
||||||
|
Nonce: 2,
|
||||||
|
To: &addr1,
|
||||||
|
Value: big.NewInt(0),
|
||||||
|
Gas: 500000,
|
||||||
|
GasPrice: newGwei(500),
|
||||||
|
}
|
||||||
|
tx := types.MustSignNewTx(key1, signer, txdata)
|
||||||
|
b.AddTx(tx)
|
||||||
|
} else if i == 2 {
|
||||||
|
txdata := &types.SetCodeTx{
|
||||||
|
ChainID: uint256.MustFromBig(gspec.Config.ChainID),
|
||||||
|
Nonce: 3,
|
||||||
|
To: addr1,
|
||||||
|
Gas: 500000,
|
||||||
|
GasFeeCap: uint256.MustFromBig(newGwei(5)),
|
||||||
|
GasTipCap: uint256.NewInt(2),
|
||||||
|
AuthList: []types.SetCodeAuthorization{auth1Reset},
|
||||||
|
}
|
||||||
|
tx := types.MustSignNewTx(key1, signer, txdata)
|
||||||
|
b.AddTx(tx)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
tracer, tracingHooks, onClose := newFirehoseTestTracer(t)
|
||||||
|
defer onClose()
|
||||||
|
|
||||||
|
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{Tracer: tracingHooks}, nil)
|
||||||
|
require.NoError(t, err, "failed to create tester chain")
|
||||||
|
|
||||||
|
defer chain.Stop()
|
||||||
|
n, err := chain.InsertChain(blocks)
|
||||||
|
require.NoError(t, err, "failed to insert chain block %d", n)
|
||||||
|
|
||||||
|
assertBlockEquals(t, tracer, filepath.Join("testdata", "TestEIP7702"), len(blocks))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,16 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"github.com/ethereum/go-ethereum/eth/tracers"
|
"github.com/ethereum/go-ethereum/eth/tracers"
|
||||||
pbeth "github.com/ethereum/go-ethereum/pb/sf/ethereum/type/v2"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
pbeth "github.com/streamingfast/firehose-ethereum/types/pb/sf/ethereum/type/v2"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"google.golang.org/protobuf/encoding/protojson"
|
"google.golang.org/protobuf/encoding/protojson"
|
||||||
|
|
@ -24,6 +28,27 @@ type firehoseInitLine struct {
|
||||||
|
|
||||||
type firehoseBlockLines []firehoseBlockLine
|
type firehoseBlockLines []firehoseBlockLine
|
||||||
|
|
||||||
|
func newFirehoseTestTracer(t *testing.T) (*tracers.Firehose, *tracing.Hooks, func()) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
tracer, err := tracers.NewFirehoseFromRawJSON([]byte(`{
|
||||||
|
"applyBackwardsCompatibility": true,
|
||||||
|
"_private": {
|
||||||
|
"flushToTestBuffer": true,
|
||||||
|
"ignoreGenesisBlock": true
|
||||||
|
}
|
||||||
|
}`))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
hooks := tracers.NewTracingHooksFromFirehose(tracer)
|
||||||
|
|
||||||
|
return tracer, hooks, func() {
|
||||||
|
if hooks.OnClose != nil {
|
||||||
|
hooks.OnClose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (lines firehoseBlockLines) assertEquals(t *testing.T, goldenDir string, expected ...firehoseBlockLineParams) {
|
func (lines firehoseBlockLines) assertEquals(t *testing.T, goldenDir string, expected ...firehoseBlockLineParams) {
|
||||||
actualParams := slicesMap(lines, func(l firehoseBlockLine) firehoseBlockLineParams { return l.Params })
|
actualParams := slicesMap(lines, func(l firehoseBlockLine) firehoseBlockLineParams { return l.Params })
|
||||||
require.Equal(t, expected, actualParams, "Actual lines block params do not match expected lines block params")
|
require.Equal(t, expected, actualParams, "Actual lines block params do not match expected lines block params")
|
||||||
|
|
@ -102,6 +127,16 @@ type firehoseBlockLineParams struct {
|
||||||
|
|
||||||
type unknownLine string
|
type unknownLine string
|
||||||
|
|
||||||
|
// assertBlockEquals reads the tracer output and compares it to the golden files in the given directory.
|
||||||
|
func assertBlockEquals(t *testing.T, tracer *tracers.Firehose, goldenDir string, expectedBlockCount int) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
genesisLine, blockLines, unknownLines := readTracerFirehoseLines(t, tracer)
|
||||||
|
require.Len(t, unknownLines, 0, "Lines:\n%s", strings.Join(slicesMap(unknownLines, func(l unknownLine) string { return "- '" + string(l) + "'" }), "\n"))
|
||||||
|
require.NotNil(t, genesisLine)
|
||||||
|
blockLines.assertOnlyBlockEquals(t, goldenDir, expectedBlockCount)
|
||||||
|
}
|
||||||
|
|
||||||
func readTracerFirehoseLines(t *testing.T, tracer *tracers.Firehose) (genesisLine *firehoseInitLine, blockLines firehoseBlockLines, unknownLines []unknownLine) {
|
func readTracerFirehoseLines(t *testing.T, tracer *tracers.Firehose) (genesisLine *firehoseInitLine, blockLines firehoseBlockLines, unknownLines []unknownLine) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
|
|
@ -157,3 +192,7 @@ func readTracerFirehoseLines(t *testing.T, tracer *tracers.Firehose) (genesisLin
|
||||||
func ptr[T any](v T) *T {
|
func ptr[T any](v T) *T {
|
||||||
return &v
|
return &v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newGwei(n int64) *big.Int {
|
||||||
|
return new(big.Int).Mul(big.NewInt(n), big.NewInt(params.GWei))
|
||||||
|
}
|
||||||
|
|
|
||||||
297
eth/tracers/internal/tracetest/firehose/testdata/TestEIP7702/block.1.golden.json
vendored
Normal file
297
eth/tracers/internal/tracetest/firehose/testdata/TestEIP7702/block.1.golden.json
vendored
Normal file
|
|
@ -0,0 +1,297 @@
|
||||||
|
{
|
||||||
|
"hash": "tNKSM8SZPvaEgBA4yUj9YayXYYuXnLCuHx5oWJwVOhw=",
|
||||||
|
"number": "1",
|
||||||
|
"size": "1190",
|
||||||
|
"header": {
|
||||||
|
"parentHash": "pWIUj7qpHz/G8tLNdaLNz8Jr1TmoyDxTXP9TdFcxi1w=",
|
||||||
|
"uncleHash": "HcxN6N7HXXqrhbVntszUGtMSRRuUinQT8KFC/UDUk0c=",
|
||||||
|
"coinbase": "AAAAAAAAAAAAAAAAAAAAAAAAqqo=",
|
||||||
|
"stateRoot": "wFieFJlWOhntuAXVWTxqg5Uur7kaXrFRERwFB8+qscc=",
|
||||||
|
"transactionsRoot": "L6HG4v+Zoguv352C8ZdQGQ4tE5BJdzCJVbfWBHMquN0=",
|
||||||
|
"receiptRoot": "6LQ+xgZZXKAlBStw088D6A2kWiz7g+TtQlAALnPMSi4=",
|
||||||
|
"logsBloom": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"difficulty": {
|
||||||
|
"bytes": "AA=="
|
||||||
|
},
|
||||||
|
"number": "1",
|
||||||
|
"gasLimit": "4712388",
|
||||||
|
"gasUsed": "142021",
|
||||||
|
"timestamp": "1970-01-01T00:00:10Z",
|
||||||
|
"mixHash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
|
||||||
|
"hash": "tNKSM8SZPvaEgBA4yUj9YayXYYuXnLCuHx5oWJwVOhw=",
|
||||||
|
"baseFeePerGas": {
|
||||||
|
"bytes": "NCdwwA=="
|
||||||
|
},
|
||||||
|
"withdrawalsRoot": "VugfFxvMVab/g0XmksD4bltI4BuZbK3AAWIvteNjtCE=",
|
||||||
|
"blobGasUsed": "0",
|
||||||
|
"excessBlobGas": "0",
|
||||||
|
"parentBeaconRoot": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
|
||||||
|
"requestsHash": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU="
|
||||||
|
},
|
||||||
|
"transactionTraces": [
|
||||||
|
{
|
||||||
|
"to": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"gasPrice": {
|
||||||
|
"bytes": "NCdwwg=="
|
||||||
|
},
|
||||||
|
"gasLimit": "500000",
|
||||||
|
"r": "E2l+Qpz16QzQhLJM+8gu8vd/lpMS1JAC0/hIlSNzFeg=",
|
||||||
|
"s": "N9pmx9wBwi0vXsT283fImtj6D4zPzYK3ZFXwBhYmbBA=",
|
||||||
|
"gasUsed": "142021",
|
||||||
|
"type": "TRX_TYPE_SET_CODE",
|
||||||
|
"maxFeePerGas": {
|
||||||
|
"bytes": "ASoF8gA="
|
||||||
|
},
|
||||||
|
"maxPriorityFeePerGas": {
|
||||||
|
"bytes": "Ag=="
|
||||||
|
},
|
||||||
|
"hash": "alLg5Yk4t0M/5q97S3ye+D/U/jP60tAc1kNI8q4G+G0=",
|
||||||
|
"from": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"beginOrdinal": "5",
|
||||||
|
"endOrdinal": "27",
|
||||||
|
"status": "SUCCEEDED",
|
||||||
|
"receipt": {
|
||||||
|
"cumulativeGasUsed": "142021",
|
||||||
|
"logsBloom": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
},
|
||||||
|
"calls": [
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"callType": "CALL",
|
||||||
|
"caller": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"address": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"addressDelegatesTo": "AAAAAAAAAAAAAAAAAAAAAAAAqqo=",
|
||||||
|
"gasLimit": "354000",
|
||||||
|
"gasConsumed": "31526",
|
||||||
|
"balanceChanges": [
|
||||||
|
{
|
||||||
|
"address": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"oldValue": {
|
||||||
|
"bytes": "DeC2s6dkAAA="
|
||||||
|
},
|
||||||
|
"newValue": {
|
||||||
|
"bytes": "Dd8ozD895cA="
|
||||||
|
},
|
||||||
|
"reason": "REASON_GAS_BUY",
|
||||||
|
"ordinal": "6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"oldValue": {
|
||||||
|
"bytes": "Dd8ozD895b8="
|
||||||
|
},
|
||||||
|
"newValue": {
|
||||||
|
"bytes": "DeBFrisGZrU="
|
||||||
|
},
|
||||||
|
"reason": "REASON_GAS_REFUND",
|
||||||
|
"ordinal": "25"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "AAAAAAAAAAAAAAAAAAAAAAAAqqo=",
|
||||||
|
"newValue": {
|
||||||
|
"bytes": "BFWK"
|
||||||
|
},
|
||||||
|
"reason": "REASON_REWARD_TRANSACTION_FEE",
|
||||||
|
"ordinal": "26"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonceChanges": [
|
||||||
|
{
|
||||||
|
"address": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"newValue": "1",
|
||||||
|
"ordinal": "8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"oldValue": "1",
|
||||||
|
"newValue": "2",
|
||||||
|
"ordinal": "9"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "cDxLK9cMFp9XFxAcruVDKZ/JRsc=",
|
||||||
|
"newValue": "1",
|
||||||
|
"ordinal": "11"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "cDxLK9cMFp9XFxAcruVDKZ/JRsc=",
|
||||||
|
"oldValue": "1",
|
||||||
|
"newValue": "2",
|
||||||
|
"ordinal": "13"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"codeChanges": [
|
||||||
|
{
|
||||||
|
"address": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"oldHash": "xdJGAYb3IzySfn2y3McDwOUAtlPKgic7e/rYBF2FpHA=",
|
||||||
|
"newHash": "6BOVhfT5ksAf8bXRTf8FXcJyKhFA0Cb18MtIsAn1Z9o=",
|
||||||
|
"newCode": "7wEAAAAAAAAAAAAAAAAAAAAAAAAAqqo=",
|
||||||
|
"ordinal": "10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "cDxLK9cMFp9XFxAcruVDKZ/JRsc=",
|
||||||
|
"oldHash": "xdJGAYb3IzySfn2y3McDwOUAtlPKgic7e/rYBF2FpHA=",
|
||||||
|
"newHash": "2nRj6FdgztYMKwAqS2x5e7pQdCMd4bTSeffx8pbIFmU=",
|
||||||
|
"newCode": "7wEAAAAAAAAAAAAAAAAAAAAAAAAAzMw=",
|
||||||
|
"ordinal": "12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "cDxLK9cMFp9XFxAcruVDKZ/JRsc=",
|
||||||
|
"oldHash": "2nRj6FdgztYMKwAqS2x5e7pQdCMd4bTSeffx8pbIFmU=",
|
||||||
|
"oldCode": "7wEAAAAAAAAAAAAAAAAAAAAAAAAAzMw=",
|
||||||
|
"newHash": "0mhxQ0BYDv3haWHrT7NIuLWUSlfUHjFwuLM/8Jt1SXA=",
|
||||||
|
"newCode": "7wEAAAAAAAAAAAAAAAAAAAAAAAAAu7s=",
|
||||||
|
"ordinal": "14"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"gasChanges": [
|
||||||
|
{
|
||||||
|
"oldValue": "500000",
|
||||||
|
"newValue": "354000",
|
||||||
|
"reason": "REASON_INTRINSIC_GAS",
|
||||||
|
"ordinal": "7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"oldValue": "353880",
|
||||||
|
"newValue": "351280",
|
||||||
|
"reason": "REASON_STATE_COLD_ACCESS",
|
||||||
|
"ordinal": "16"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"oldValue": "353980",
|
||||||
|
"newValue": "5348",
|
||||||
|
"reason": "REASON_CALL",
|
||||||
|
"ordinal": "17"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"oldValue": "5348",
|
||||||
|
"newValue": "322474",
|
||||||
|
"reason": "REASON_REFUND_AFTER_EXECUTION",
|
||||||
|
"ordinal": "23"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"endOrdinal": "24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 2,
|
||||||
|
"parentIndex": 1,
|
||||||
|
"depth": 1,
|
||||||
|
"callType": "CALL",
|
||||||
|
"caller": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"address": "cDxLK9cMFp9XFxAcruVDKZ/JRsc=",
|
||||||
|
"addressDelegatesTo": "AAAAAAAAAAAAAAAAAAAAAAAAu7s=",
|
||||||
|
"value": {
|
||||||
|
"bytes": "AQ=="
|
||||||
|
},
|
||||||
|
"gasLimit": "339232",
|
||||||
|
"gasConsumed": "22106",
|
||||||
|
"storageChanges": [
|
||||||
|
{
|
||||||
|
"address": "cDxLK9cMFp9XFxAcruVDKZ/JRsc=",
|
||||||
|
"key": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEI=",
|
||||||
|
"oldValue": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
|
||||||
|
"newValue": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEI=",
|
||||||
|
"ordinal": "21"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"balanceChanges": [
|
||||||
|
{
|
||||||
|
"address": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"oldValue": {
|
||||||
|
"bytes": "Dd8ozD895cA="
|
||||||
|
},
|
||||||
|
"newValue": {
|
||||||
|
"bytes": "Dd8ozD895b8="
|
||||||
|
},
|
||||||
|
"reason": "REASON_TRANSFER",
|
||||||
|
"ordinal": "19"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "cDxLK9cMFp9XFxAcruVDKZ/JRsc=",
|
||||||
|
"oldValue": {
|
||||||
|
"bytes": "DeC2s6dkAAA="
|
||||||
|
},
|
||||||
|
"newValue": {
|
||||||
|
"bytes": "DeC2s6dkAAE="
|
||||||
|
},
|
||||||
|
"reason": "REASON_TRANSFER",
|
||||||
|
"ordinal": "20"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"beginOrdinal": "18",
|
||||||
|
"endOrdinal": "22"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"setCodeAuthorizations": [
|
||||||
|
{
|
||||||
|
"chainId": "AQ==",
|
||||||
|
"nonce": "1",
|
||||||
|
"v": 1,
|
||||||
|
"r": "9+Pll/wJfnHtbCaxSyXlOVvIUQ1YuRNq9DnhJxXy1yE=",
|
||||||
|
"s": "bPfD15Ob/beENz7/wOuwvXVJaRpRPzlePNq/hgJySYc=",
|
||||||
|
"authority": "cVYrcZmYc9tbKG35V68ZnslGF/c="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"r": "2uP1vwtGC/qSZin0z+PZ2kBZ/xY3445BRUpUUwr4UOc=",
|
||||||
|
"s": "HhA+a0fj/u82ZZyD9gMoHso5vGditId+wkZrJcpo4UM=",
|
||||||
|
"authority": "cDxLK9cMFp9XFxAcruVDKZ/JRsc="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"discarded": true,
|
||||||
|
"v": 4,
|
||||||
|
"r": "2uP1vwtGC/qSZin0z+PZ2kBZ/xY3445BRUpUUwr4UOc=",
|
||||||
|
"s": "HhA+a0fj/u82ZZyD9gMoHso5vGditId+wkZrJcpo4UM="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nonce": "1",
|
||||||
|
"r": "aZRYP4l48gpWJSypjCxSptjK/kDFXmphIXOrnH6LlKs=",
|
||||||
|
"s": "HLb0WRaaPuzez2ZbtK39Ch9vZGXNjm5AYg2i8X5MMwg=",
|
||||||
|
"authority": "cDxLK9cMFp9XFxAcruVDKZ/JRsc="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"discarded": true,
|
||||||
|
"nonce": "1",
|
||||||
|
"r": "aZRYP4l48gpWJSypjCxSptjK/kDFXmphIXOrnH6LlKs=",
|
||||||
|
"s": "HLb0WRaaPuzez2ZbtK39Ch9vZGXNjm5AYg2i8X5MMwg=",
|
||||||
|
"authority": "cDxLK9cMFp9XFxAcruVDKZ/JRsc="
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"systemCalls": [
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"callType": "CALL",
|
||||||
|
"caller": "//////////////////////////4=",
|
||||||
|
"address": "AA899tcygH7xMZ+3uLuFItC+rAI=",
|
||||||
|
"gasLimit": "30000000",
|
||||||
|
"input": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
|
||||||
|
"endOrdinal": "2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"callType": "CALL",
|
||||||
|
"caller": "//////////////////////////4=",
|
||||||
|
"address": "AAD5CCfxxToQy3oCM1sXUyAAKTU=",
|
||||||
|
"gasLimit": "30000000",
|
||||||
|
"input": "pWIUj7qpHz/G8tLNdaLNz8Jr1TmoyDxTXP9TdFcxi1w=",
|
||||||
|
"endOrdinal": "4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"callType": "CALL",
|
||||||
|
"caller": "//////////////////////////4=",
|
||||||
|
"address": "AAAJYe9IDrVegNGa2DV5pkwAcAI=",
|
||||||
|
"gasLimit": "30000000",
|
||||||
|
"endOrdinal": "29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"callType": "CALL",
|
||||||
|
"caller": "//////////////////////////4=",
|
||||||
|
"address": "AAC73cfOSIZC+1efiwDzpZAAclE=",
|
||||||
|
"gasLimit": "30000000",
|
||||||
|
"endOrdinal": "31"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ver": 3
|
||||||
|
}
|
||||||
218
eth/tracers/internal/tracetest/firehose/testdata/TestEIP7702/block.2.golden.json
vendored
Normal file
218
eth/tracers/internal/tracetest/firehose/testdata/TestEIP7702/block.2.golden.json
vendored
Normal file
|
|
@ -0,0 +1,218 @@
|
||||||
|
{
|
||||||
|
"hash": "Hlau1KLprrOkaDe4TNZdPEoXeJ4UGEL1PwUY/qq+/rk=",
|
||||||
|
"number": "2",
|
||||||
|
"size": "717",
|
||||||
|
"header": {
|
||||||
|
"parentHash": "tNKSM8SZPvaEgBA4yUj9YayXYYuXnLCuHx5oWJwVOhw=",
|
||||||
|
"uncleHash": "HcxN6N7HXXqrhbVntszUGtMSRRuUinQT8KFC/UDUk0c=",
|
||||||
|
"coinbase": "AAAAAAAAAAAAAAAAAAAAAAAAqqo=",
|
||||||
|
"stateRoot": "C/zDETYPAXEFuq3RDENkXppoaNjfcWKHhIQqZGC0D5c=",
|
||||||
|
"transactionsRoot": "5SXnkgZs4gKgt8t4GTnSeoV1i17zHn3xbZXSln9fd2E=",
|
||||||
|
"receiptRoot": "TaaZwIwiwzd65OYkLzazOIYrFN0/DnyXzNqaA/dY3pQ=",
|
||||||
|
"logsBloom": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"difficulty": {
|
||||||
|
"bytes": "AA=="
|
||||||
|
},
|
||||||
|
"number": "2",
|
||||||
|
"gasLimit": "4712388",
|
||||||
|
"gasUsed": "35126",
|
||||||
|
"timestamp": "1970-01-01T00:00:20Z",
|
||||||
|
"mixHash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
|
||||||
|
"hash": "Hlau1KLprrOkaDe4TNZdPEoXeJ4UGEL1PwUY/qq+/rk=",
|
||||||
|
"baseFeePerGas": {
|
||||||
|
"bytes": "LgcbLA=="
|
||||||
|
},
|
||||||
|
"withdrawalsRoot": "VugfFxvMVab/g0XmksD4bltI4BuZbK3AAWIvteNjtCE=",
|
||||||
|
"blobGasUsed": "0",
|
||||||
|
"excessBlobGas": "0",
|
||||||
|
"parentBeaconRoot": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
|
||||||
|
"requestsHash": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU="
|
||||||
|
},
|
||||||
|
"transactionTraces": [
|
||||||
|
{
|
||||||
|
"to": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"nonce": "2",
|
||||||
|
"gasPrice": {
|
||||||
|
"bytes": "dGpSiAA="
|
||||||
|
},
|
||||||
|
"gasLimit": "500000",
|
||||||
|
"v": "JQ==",
|
||||||
|
"r": "llnySTXnLA5URm+RriiJTQ4gvkdUifLtVOIyBCpDFTw=",
|
||||||
|
"s": "SsqOfVDTp1cpwvz0g4nLhIzrWRGwh0Jgz4l9GK/UHbE=",
|
||||||
|
"gasUsed": "35126",
|
||||||
|
"hash": "TNmQOfjPE0jeas0eba+xGMaitDgyCOKmvNIBapciCiE=",
|
||||||
|
"from": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"beginOrdinal": "5",
|
||||||
|
"endOrdinal": "21",
|
||||||
|
"status": "SUCCEEDED",
|
||||||
|
"receipt": {
|
||||||
|
"cumulativeGasUsed": "35126",
|
||||||
|
"logsBloom": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
},
|
||||||
|
"calls": [
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"callType": "CALL",
|
||||||
|
"caller": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"address": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"addressDelegatesTo": "AAAAAAAAAAAAAAAAAAAAAAAAqqo=",
|
||||||
|
"gasLimit": "479000",
|
||||||
|
"gasConsumed": "14126",
|
||||||
|
"balanceChanges": [
|
||||||
|
{
|
||||||
|
"address": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"oldValue": {
|
||||||
|
"bytes": "DeBFrisGZrU="
|
||||||
|
},
|
||||||
|
"newValue": {
|
||||||
|
"bytes": "CmgYAUEtZrU="
|
||||||
|
},
|
||||||
|
"reason": "REASON_GAS_BUY",
|
||||||
|
"ordinal": "6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"oldValue": {
|
||||||
|
"bytes": "CmgYAUEtZrQ="
|
||||||
|
},
|
||||||
|
"newValue": {
|
||||||
|
"bytes": "DaHgOZLVtrQ="
|
||||||
|
},
|
||||||
|
"reason": "REASON_GAS_REFUND",
|
||||||
|
"ordinal": "19"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "AAAAAAAAAAAAAAAAAAAAAAAAqqo=",
|
||||||
|
"oldValue": {
|
||||||
|
"bytes": "BFWK"
|
||||||
|
},
|
||||||
|
"newValue": {
|
||||||
|
"bytes": "PkzJFSq+Qg=="
|
||||||
|
},
|
||||||
|
"reason": "REASON_REWARD_TRANSACTION_FEE",
|
||||||
|
"ordinal": "20"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonceChanges": [
|
||||||
|
{
|
||||||
|
"address": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"oldValue": "2",
|
||||||
|
"newValue": "3",
|
||||||
|
"ordinal": "8"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"gasChanges": [
|
||||||
|
{
|
||||||
|
"oldValue": "500000",
|
||||||
|
"newValue": "479000",
|
||||||
|
"reason": "REASON_INTRINSIC_GAS",
|
||||||
|
"ordinal": "7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"oldValue": "478880",
|
||||||
|
"newValue": "476380",
|
||||||
|
"reason": "REASON_STATE_COLD_ACCESS",
|
||||||
|
"ordinal": "10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"oldValue": "476380",
|
||||||
|
"newValue": "473780",
|
||||||
|
"reason": "REASON_STATE_COLD_ACCESS",
|
||||||
|
"ordinal": "11"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"oldValue": "478980",
|
||||||
|
"newValue": "7262",
|
||||||
|
"reason": "REASON_CALL",
|
||||||
|
"ordinal": "12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"oldValue": "7262",
|
||||||
|
"newValue": "464874",
|
||||||
|
"reason": "REASON_REFUND_AFTER_EXECUTION",
|
||||||
|
"ordinal": "17"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"endOrdinal": "18"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 2,
|
||||||
|
"parentIndex": 1,
|
||||||
|
"depth": 1,
|
||||||
|
"callType": "CALL",
|
||||||
|
"caller": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"address": "cDxLK9cMFp9XFxAcruVDKZ/JRsc=",
|
||||||
|
"addressDelegatesTo": "AAAAAAAAAAAAAAAAAAAAAAAAu7s=",
|
||||||
|
"value": {
|
||||||
|
"bytes": "AQ=="
|
||||||
|
},
|
||||||
|
"gasLimit": "459818",
|
||||||
|
"gasConsumed": "2206",
|
||||||
|
"balanceChanges": [
|
||||||
|
{
|
||||||
|
"address": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"oldValue": {
|
||||||
|
"bytes": "CmgYAUEtZrU="
|
||||||
|
},
|
||||||
|
"newValue": {
|
||||||
|
"bytes": "CmgYAUEtZrQ="
|
||||||
|
},
|
||||||
|
"reason": "REASON_TRANSFER",
|
||||||
|
"ordinal": "14"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "cDxLK9cMFp9XFxAcruVDKZ/JRsc=",
|
||||||
|
"oldValue": {
|
||||||
|
"bytes": "DeC2s6dkAAE="
|
||||||
|
},
|
||||||
|
"newValue": {
|
||||||
|
"bytes": "DeC2s6dkAAI="
|
||||||
|
},
|
||||||
|
"reason": "REASON_TRANSFER",
|
||||||
|
"ordinal": "15"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"beginOrdinal": "13",
|
||||||
|
"endOrdinal": "16"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"systemCalls": [
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"callType": "CALL",
|
||||||
|
"caller": "//////////////////////////4=",
|
||||||
|
"address": "AA899tcygH7xMZ+3uLuFItC+rAI=",
|
||||||
|
"gasLimit": "30000000",
|
||||||
|
"input": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
|
||||||
|
"endOrdinal": "2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"callType": "CALL",
|
||||||
|
"caller": "//////////////////////////4=",
|
||||||
|
"address": "AAD5CCfxxToQy3oCM1sXUyAAKTU=",
|
||||||
|
"gasLimit": "30000000",
|
||||||
|
"input": "tNKSM8SZPvaEgBA4yUj9YayXYYuXnLCuHx5oWJwVOhw=",
|
||||||
|
"endOrdinal": "4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"callType": "CALL",
|
||||||
|
"caller": "//////////////////////////4=",
|
||||||
|
"address": "AAAJYe9IDrVegNGa2DV5pkwAcAI=",
|
||||||
|
"gasLimit": "30000000",
|
||||||
|
"endOrdinal": "23"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"callType": "CALL",
|
||||||
|
"caller": "//////////////////////////4=",
|
||||||
|
"address": "AAC73cfOSIZC+1efiwDzpZAAclE=",
|
||||||
|
"gasLimit": "30000000",
|
||||||
|
"endOrdinal": "25"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ver": 3
|
||||||
|
}
|
||||||
182
eth/tracers/internal/tracetest/firehose/testdata/TestEIP7702/block.3.golden.json
vendored
Normal file
182
eth/tracers/internal/tracetest/firehose/testdata/TestEIP7702/block.3.golden.json
vendored
Normal file
|
|
@ -0,0 +1,182 @@
|
||||||
|
{
|
||||||
|
"hash": "nM0MjYrd54p5L0zQNGpHV7fxetFL1VCejCvGELDLop8=",
|
||||||
|
"number": "3",
|
||||||
|
"size": "817",
|
||||||
|
"header": {
|
||||||
|
"parentHash": "Hlau1KLprrOkaDe4TNZdPEoXeJ4UGEL1PwUY/qq+/rk=",
|
||||||
|
"uncleHash": "HcxN6N7HXXqrhbVntszUGtMSRRuUinQT8KFC/UDUk0c=",
|
||||||
|
"coinbase": "AAAAAAAAAAAAAAAAAAAAAAAAqqo=",
|
||||||
|
"stateRoot": "vWvMYC8Hck2r4d77C3bO7nRWmEtpytSHv092DGpMjeI=",
|
||||||
|
"transactionsRoot": "Bpo3ARUhIUuu9hH3yrkUNF2s22VFnHRDwdWxzM0pb5U=",
|
||||||
|
"receiptRoot": "A2x9IEIO284ktQYhSLzoBWO0j9RTL7HAaLLJalMRcBk=",
|
||||||
|
"logsBloom": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"difficulty": {
|
||||||
|
"bytes": "AA=="
|
||||||
|
},
|
||||||
|
"number": "3",
|
||||||
|
"gasLimit": "4712388",
|
||||||
|
"gasUsed": "36800",
|
||||||
|
"timestamp": "1970-01-01T00:00:30Z",
|
||||||
|
"mixHash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
|
||||||
|
"hash": "nM0MjYrd54p5L0zQNGpHV7fxetFL1VCejCvGELDLop8=",
|
||||||
|
"baseFeePerGas": {
|
||||||
|
"bytes": "KFws9Q=="
|
||||||
|
},
|
||||||
|
"withdrawalsRoot": "VugfFxvMVab/g0XmksD4bltI4BuZbK3AAWIvteNjtCE=",
|
||||||
|
"blobGasUsed": "0",
|
||||||
|
"excessBlobGas": "0",
|
||||||
|
"parentBeaconRoot": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
|
||||||
|
"requestsHash": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU="
|
||||||
|
},
|
||||||
|
"transactionTraces": [
|
||||||
|
{
|
||||||
|
"to": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"nonce": "3",
|
||||||
|
"gasPrice": {
|
||||||
|
"bytes": "KFws9w=="
|
||||||
|
},
|
||||||
|
"gasLimit": "500000",
|
||||||
|
"r": "3+bIOst9jVy0xdYLs7dP1KfP1XrtsXepmpY0W3XBKII=",
|
||||||
|
"s": "UGXb+KJ8dparEBn0Wb2lX5fh1gB2+AiHfowzzmJWOkE=",
|
||||||
|
"gasUsed": "36800",
|
||||||
|
"type": "TRX_TYPE_SET_CODE",
|
||||||
|
"maxFeePerGas": {
|
||||||
|
"bytes": "ASoF8gA="
|
||||||
|
},
|
||||||
|
"maxPriorityFeePerGas": {
|
||||||
|
"bytes": "Ag=="
|
||||||
|
},
|
||||||
|
"hash": "vj4lUeVR72WjVf2OYUmz3Um0SH4d6qCao7cZRbBiaCI=",
|
||||||
|
"from": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"beginOrdinal": "5",
|
||||||
|
"endOrdinal": "15",
|
||||||
|
"status": "SUCCEEDED",
|
||||||
|
"receipt": {
|
||||||
|
"cumulativeGasUsed": "36800",
|
||||||
|
"logsBloom": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
},
|
||||||
|
"calls": [
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"callType": "CALL",
|
||||||
|
"caller": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"address": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"gasLimit": "454000",
|
||||||
|
"balanceChanges": [
|
||||||
|
{
|
||||||
|
"address": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"oldValue": {
|
||||||
|
"bytes": "DaHgOZLVtrQ="
|
||||||
|
},
|
||||||
|
"newValue": {
|
||||||
|
"bytes": "DaCsTVRHwNQ="
|
||||||
|
},
|
||||||
|
"reason": "REASON_GAS_BUY",
|
||||||
|
"ordinal": "6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"oldValue": {
|
||||||
|
"bytes": "DaCsTVRHwNQ="
|
||||||
|
},
|
||||||
|
"newValue": {
|
||||||
|
"bytes": "DaHJj9CWBHQ="
|
||||||
|
},
|
||||||
|
"reason": "REASON_GAS_REFUND",
|
||||||
|
"ordinal": "13"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "AAAAAAAAAAAAAAAAAAAAAAAAqqo=",
|
||||||
|
"oldValue": {
|
||||||
|
"bytes": "PkzJFSq+Qg=="
|
||||||
|
},
|
||||||
|
"newValue": {
|
||||||
|
"bytes": "PkzJFSvdwg=="
|
||||||
|
},
|
||||||
|
"reason": "REASON_REWARD_TRANSACTION_FEE",
|
||||||
|
"ordinal": "14"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonceChanges": [
|
||||||
|
{
|
||||||
|
"address": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"oldValue": "3",
|
||||||
|
"newValue": "4",
|
||||||
|
"ordinal": "8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"oldValue": "4",
|
||||||
|
"newValue": "5",
|
||||||
|
"ordinal": "9"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"codeChanges": [
|
||||||
|
{
|
||||||
|
"address": "cVYrcZmYc9tbKG35V68ZnslGF/c=",
|
||||||
|
"oldHash": "6BOVhfT5ksAf8bXRTf8FXcJyKhFA0Cb18MtIsAn1Z9o=",
|
||||||
|
"oldCode": "7wEAAAAAAAAAAAAAAAAAAAAAAAAAqqo=",
|
||||||
|
"newHash": "xdJGAYb3IzySfn2y3McDwOUAtlPKgic7e/rYBF2FpHA=",
|
||||||
|
"ordinal": "10"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"gasChanges": [
|
||||||
|
{
|
||||||
|
"oldValue": "500000",
|
||||||
|
"newValue": "454000",
|
||||||
|
"reason": "REASON_INTRINSIC_GAS",
|
||||||
|
"ordinal": "7"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"endOrdinal": "12"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"setCodeAuthorizations": [
|
||||||
|
{
|
||||||
|
"chainId": "AQ==",
|
||||||
|
"nonce": "4",
|
||||||
|
"r": "8RpcvObxuhW9b2SyJDTKMBtrqfyaAJlzS37bOLPTKIo=",
|
||||||
|
"s": "NMkyzSai5xkwNV4ttrTli9jZHXeB7hUwej28frcnTDw=",
|
||||||
|
"authority": "cVYrcZmYc9tbKG35V68ZnslGF/c="
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"systemCalls": [
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"callType": "CALL",
|
||||||
|
"caller": "//////////////////////////4=",
|
||||||
|
"address": "AA899tcygH7xMZ+3uLuFItC+rAI=",
|
||||||
|
"gasLimit": "30000000",
|
||||||
|
"input": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
|
||||||
|
"endOrdinal": "2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"callType": "CALL",
|
||||||
|
"caller": "//////////////////////////4=",
|
||||||
|
"address": "AAD5CCfxxToQy3oCM1sXUyAAKTU=",
|
||||||
|
"gasLimit": "30000000",
|
||||||
|
"input": "Hlau1KLprrOkaDe4TNZdPEoXeJ4UGEL1PwUY/qq+/rk=",
|
||||||
|
"endOrdinal": "4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"callType": "CALL",
|
||||||
|
"caller": "//////////////////////////4=",
|
||||||
|
"address": "AAAJYe9IDrVegNGa2DV5pkwAcAI=",
|
||||||
|
"gasLimit": "30000000",
|
||||||
|
"endOrdinal": "17"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"callType": "CALL",
|
||||||
|
"caller": "//////////////////////////4=",
|
||||||
|
"address": "AAC73cfOSIZC+1efiwDzpZAAclE=",
|
||||||
|
"gasLimit": "30000000",
|
||||||
|
"endOrdinal": "19"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ver": 3
|
||||||
|
}
|
||||||
1
go.mod
1
go.mod
|
|
@ -58,6 +58,7 @@ require (
|
||||||
github.com/rs/cors v1.7.0
|
github.com/rs/cors v1.7.0
|
||||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible
|
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible
|
||||||
github.com/status-im/keycard-go v0.2.0
|
github.com/status-im/keycard-go v0.2.0
|
||||||
|
github.com/streamingfast/firehose-ethereum/types v0.0.0-20250219193809-31f4c76a8a5d
|
||||||
github.com/stretchr/testify v1.9.0
|
github.com/stretchr/testify v1.9.0
|
||||||
github.com/supranational/blst v0.3.14
|
github.com/supranational/blst v0.3.14
|
||||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
|
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
|
||||||
|
|
|
||||||
2
go.sum
2
go.sum
|
|
@ -493,6 +493,8 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
|
||||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||||
github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA=
|
github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA=
|
||||||
github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg=
|
github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg=
|
||||||
|
github.com/streamingfast/firehose-ethereum/types v0.0.0-20250219193809-31f4c76a8a5d h1:8Ki6y+B7HB3Wo8DBUqoIpNxT6mGZ/5joPHRZSvLIFdE=
|
||||||
|
github.com/streamingfast/firehose-ethereum/types v0.0.0-20250219193809-31f4c76a8a5d/go.mod h1:CG22ObinxSbKIP19bAj0uro0a290kzZTiBbjL8VR0SE=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
package pbeth
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/hex"
|
|
||||||
"math/big"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var b0 = big.NewInt(0)
|
|
||||||
|
|
||||||
func (b *Block) PreviousID() string {
|
|
||||||
return hex.EncodeToString(b.Header.ParentHash)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Block) Time() time.Time {
|
|
||||||
return b.Header.Timestamp.AsTime()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *BigInt) Native() *big.Int {
|
|
||||||
if m == nil {
|
|
||||||
return b0
|
|
||||||
}
|
|
||||||
|
|
||||||
z := new(big.Int)
|
|
||||||
z.SetBytes(m.Bytes)
|
|
||||||
return z
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue