mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-15 00:13:46 +00:00
Re-implemented OnGenesisBlock using the tracer itself
This commit is contained in:
parent
09df0e0c95
commit
d1ad0e35d5
1 changed files with 49 additions and 98 deletions
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -38,6 +37,9 @@ var _ core.BlockchainLogger = (*Firehose)(nil)
|
||||||
var emptyAddress = common.Address{}.Bytes()
|
var emptyAddress = common.Address{}.Bytes()
|
||||||
var emptyHash = common.Hash{}.Bytes()
|
var emptyHash = common.Hash{}.Bytes()
|
||||||
|
|
||||||
|
var emptyCommonAddress = common.Address{}
|
||||||
|
var emptyCommonHash = common.Hash{}
|
||||||
|
|
||||||
type Firehose struct {
|
type Firehose struct {
|
||||||
// Global state
|
// Global state
|
||||||
outputBuffer *bytes.Buffer
|
outputBuffer *bytes.Buffer
|
||||||
|
|
@ -146,9 +148,6 @@ func (f *Firehose) CaptureTxStart(evm *vm.EVM, tx *types.Transaction) {
|
||||||
|
|
||||||
f.ensureInBlockAndNotInTrxAndNotInCall()
|
f.ensureInBlockAndNotInTrxAndNotInCall()
|
||||||
|
|
||||||
f.inTransaction.Store(true)
|
|
||||||
f.isPrecompiledAddr = evm.IsPrecompileAddr
|
|
||||||
|
|
||||||
signer := types.MakeSigner(evm.ChainConfig(), evm.Context.BlockNumber, evm.Context.Time)
|
signer := types.MakeSigner(evm.ChainConfig(), evm.Context.BlockNumber, evm.Context.Time)
|
||||||
|
|
||||||
from, err := types.Sender(signer, tx)
|
from, err := types.Sender(signer, tx)
|
||||||
|
|
@ -163,11 +162,21 @@ func (f *Firehose) CaptureTxStart(evm *vm.EVM, tx *types.Transaction) {
|
||||||
to = *tx.To()
|
to = *tx.To()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f.captureTxStart(tx, tx.Hash(), from, to, evm.IsPrecompileAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// captureTxStart is used internally a two places, in the normal "tracer" and in the "OnGenesisBlock",
|
||||||
|
// we manually pass some override to the `tx` because genesis block has a different way of creating
|
||||||
|
// the transaction that wraps the genesis block.
|
||||||
|
func (f *Firehose) captureTxStart(tx *types.Transaction, hash common.Hash, from, to common.Address, isPrecompiledAddr func(common.Address) bool) {
|
||||||
|
f.inTransaction.Store(true)
|
||||||
|
f.isPrecompiledAddr = isPrecompiledAddr
|
||||||
|
|
||||||
v, r, s := tx.RawSignatureValues()
|
v, r, s := tx.RawSignatureValues()
|
||||||
|
|
||||||
f.transaction = &pbeth.TransactionTrace{
|
f.transaction = &pbeth.TransactionTrace{
|
||||||
BeginOrdinal: f.blockOrdinal.Next(),
|
BeginOrdinal: f.blockOrdinal.Next(),
|
||||||
Hash: tx.Hash().Bytes(),
|
Hash: hash.Bytes(),
|
||||||
From: from.Bytes(),
|
From: from.Bytes(),
|
||||||
To: to.Bytes(),
|
To: to.Bytes(),
|
||||||
Nonce: tx.Nonce(),
|
Nonce: tx.Nonce(),
|
||||||
|
|
@ -469,104 +478,40 @@ func (f *Firehose) CaptureKeccakPreimage(hash common.Hash, data []byte) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Firehose) OnGenesisBlock(b *types.Block, alloc core.GenesisAlloc) {
|
func (f *Firehose) OnGenesisBlock(b *types.Block, alloc core.GenesisAlloc) {
|
||||||
// FIXME: Re-implement by actualling callin `OnBlockStart/OnTrxStart/CaptureStart` etc.
|
f.OnBlockStart(b, big.NewInt(0), nil, nil)
|
||||||
block := &pbeth.Block{
|
f.captureTxStart(types.NewTx(&types.LegacyTx{}), emptyCommonHash, emptyCommonAddress, emptyCommonAddress, func(common.Address) bool { return false })
|
||||||
Hash: b.Hash().Bytes(),
|
f.CaptureStart(emptyCommonAddress, emptyCommonAddress, false, nil, 0, nil)
|
||||||
Number: b.Number().Uint64(),
|
|
||||||
Header: newBlockHeaderFromChainBlock(b, firehoseBigIntFromNative(b.Difficulty())),
|
|
||||||
TransactionTraces: []*pbeth.TransactionTrace{
|
|
||||||
{
|
|
||||||
BeginOrdinal: f.blockOrdinal.Next(),
|
|
||||||
Hash: emptyHash,
|
|
||||||
From: emptyAddress,
|
|
||||||
To: emptyAddress,
|
|
||||||
Receipt: &pbeth.TransactionReceipt{
|
|
||||||
StateRoot: b.Root().Bytes(),
|
|
||||||
LogsBloom: types.Bloom{}.Bytes(),
|
|
||||||
},
|
|
||||||
Status: pbeth.TransactionTraceStatus_SUCCEEDED,
|
|
||||||
Calls: []*pbeth.Call{
|
|
||||||
{
|
|
||||||
// It seems we never properly set the BeginOrdinal/EndOrdinal of the root call of the genesis block
|
|
||||||
BeginOrdinal: 0,
|
|
||||||
EndOrdinal: 0,
|
|
||||||
|
|
||||||
CallType: pbeth.CallType_CALL,
|
|
||||||
Caller: emptyAddress,
|
|
||||||
Address: emptyAddress,
|
|
||||||
Index: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Size: uint64(b.Size()),
|
|
||||||
Ver: 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
rootTrx := block.TransactionTraces[0]
|
|
||||||
rootCall := rootTrx.Calls[0]
|
|
||||||
|
|
||||||
sortedAddrs := make([]common.Address, len(alloc))
|
|
||||||
i := 0
|
|
||||||
for addr := range alloc {
|
|
||||||
sortedAddrs[i] = addr
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Slice(sortedAddrs, func(i, j int) bool {
|
|
||||||
return bytes.Compare(sortedAddrs[i][:], sortedAddrs[j][:]) <= -1
|
|
||||||
})
|
|
||||||
|
|
||||||
for _, addr := range sortedKeys(alloc) {
|
for _, addr := range sortedKeys(alloc) {
|
||||||
account := alloc[addr]
|
account := alloc[addr]
|
||||||
|
|
||||||
rootCall.AccountCreations = append(rootCall.AccountCreations, &pbeth.AccountCreation{
|
f.OnNewAccount(addr)
|
||||||
Account: addr.Bytes(),
|
|
||||||
Ordinal: f.blockOrdinal.Next(),
|
|
||||||
})
|
|
||||||
|
|
||||||
rootCall.BalanceChanges = append(rootCall.BalanceChanges, &pbeth.BalanceChange{
|
if account.Balance != nil && account.Balance.Sign() != 0 {
|
||||||
Address: addr.Bytes(),
|
activeCall := f.callStack.Peek()
|
||||||
NewValue: firehoseBigIntFromNative(account.Balance),
|
activeCall.BalanceChanges = append(activeCall.BalanceChanges, f.newBalanceChange("genesis", addr, common.Big0, account.Balance, pbeth.BalanceChange_REASON_GENESIS_BALANCE))
|
||||||
Reason: pbeth.BalanceChange_REASON_GENESIS_BALANCE,
|
}
|
||||||
Ordinal: f.blockOrdinal.Next(),
|
|
||||||
})
|
|
||||||
|
|
||||||
if len(account.Code) > 0 {
|
if len(account.Code) > 0 {
|
||||||
rootCall.CodeChanges = append(rootCall.CodeChanges, &pbeth.CodeChange{
|
f.OnCodeChange(addr, emptyCommonHash, nil, common.BytesToHash(crypto.Keccak256(account.Code)), account.Code)
|
||||||
Address: addr.Bytes(),
|
|
||||||
NewCode: account.Code,
|
|
||||||
NewHash: crypto.Keccak256(account.Code),
|
|
||||||
Ordinal: f.blockOrdinal.Next(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if account.Nonce > 0 {
|
if account.Nonce > 0 {
|
||||||
rootCall.NonceChanges = append(rootCall.NonceChanges, &pbeth.NonceChange{
|
f.OnNonceChange(addr, 0, account.Nonce)
|
||||||
Address: addr.Bytes(),
|
|
||||||
OldValue: 0,
|
|
||||||
NewValue: account.Nonce,
|
|
||||||
Ordinal: f.blockOrdinal.Next(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is bad, we were not sorting the storage changes before! Not a big deal,
|
|
||||||
// just make it harder for verifiability of previous blocks, they are now sorted.
|
|
||||||
for _, key := range sortedKeys(account.Storage) {
|
for _, key := range sortedKeys(account.Storage) {
|
||||||
rootCall.StorageChanges = append(rootCall.StorageChanges, &pbeth.StorageChange{
|
f.OnStorageChange(addr, key, emptyCommonHash, account.Storage[key])
|
||||||
Address: addr.Bytes(),
|
|
||||||
Key: key.Bytes(),
|
|
||||||
NewValue: account.Storage[key].Bytes(),
|
|
||||||
Ordinal: f.blockOrdinal.Next(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ordering matters here, we must set the end ordinal of the call before the transaction
|
f.CaptureEnd(nil, 0, nil)
|
||||||
rootTrx.EndOrdinal = f.blockOrdinal.Next()
|
f.CaptureTxEnd(&types.Receipt{
|
||||||
|
Type: uint8(types.LegacyTxType),
|
||||||
f.printBlockToFirehose(block)
|
PostState: b.Root().Bytes(),
|
||||||
f.resetBlock()
|
Status: types.ReceiptStatusSuccessful,
|
||||||
|
}, nil)
|
||||||
|
f.OnBlockEnd(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
type bytesGetter interface {
|
type bytesGetter interface {
|
||||||
|
|
@ -591,17 +536,7 @@ func (f *Firehose) OnBalanceChange(a common.Address, prev, new *big.Int, reason
|
||||||
|
|
||||||
f.ensureInBlockOrTrx()
|
f.ensureInBlockOrTrx()
|
||||||
|
|
||||||
change := &pbeth.BalanceChange{
|
change := f.newBalanceChange("tracer", a, prev, new, balanceChangeReasonFromChain(reason))
|
||||||
Ordinal: f.blockOrdinal.Next(),
|
|
||||||
Address: a.Bytes(),
|
|
||||||
OldValue: firehoseBigIntFromNative(prev),
|
|
||||||
NewValue: firehoseBigIntFromNative(new),
|
|
||||||
Reason: balanceChangeReasonFromChain(reason),
|
|
||||||
}
|
|
||||||
|
|
||||||
if change.Reason == pbeth.BalanceChange_REASON_UNKNOWN {
|
|
||||||
panic(fmt.Errorf("unknown balance change reason %s from code %d not accepted here", change.Reason, reason))
|
|
||||||
}
|
|
||||||
|
|
||||||
if f.inTransaction.Load() {
|
if f.inTransaction.Load() {
|
||||||
activeCall := f.callStack.Peek()
|
activeCall := f.callStack.Peek()
|
||||||
|
|
@ -618,6 +553,22 @@ 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 {
|
||||||
|
firehoseTrace("balance changed tag=%s before=%d after=%d reason=%s", tag, oldValue, newValue, reason)
|
||||||
|
|
||||||
|
if reason == pbeth.BalanceChange_REASON_UNKNOWN {
|
||||||
|
panic(fmt.Errorf("received unknown balance change reason %s", reason))
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pbeth.BalanceChange{
|
||||||
|
Ordinal: f.blockOrdinal.Next(),
|
||||||
|
Address: address.Bytes(),
|
||||||
|
OldValue: firehoseBigIntFromNative(oldValue),
|
||||||
|
NewValue: firehoseBigIntFromNative(newValue),
|
||||||
|
Reason: reason,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (f *Firehose) OnNonceChange(a common.Address, prev, new uint64) {
|
func (f *Firehose) OnNonceChange(a common.Address, prev, new uint64) {
|
||||||
f.ensureInBlockAndInTrx()
|
f.ensureInBlockAndInTrx()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue