mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-01 01:23: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"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
|
@ -38,6 +37,9 @@ var _ core.BlockchainLogger = (*Firehose)(nil)
|
|||
var emptyAddress = common.Address{}.Bytes()
|
||||
var emptyHash = common.Hash{}.Bytes()
|
||||
|
||||
var emptyCommonAddress = common.Address{}
|
||||
var emptyCommonHash = common.Hash{}
|
||||
|
||||
type Firehose struct {
|
||||
// Global state
|
||||
outputBuffer *bytes.Buffer
|
||||
|
|
@ -146,9 +148,6 @@ func (f *Firehose) CaptureTxStart(evm *vm.EVM, tx *types.Transaction) {
|
|||
|
||||
f.ensureInBlockAndNotInTrxAndNotInCall()
|
||||
|
||||
f.inTransaction.Store(true)
|
||||
f.isPrecompiledAddr = evm.IsPrecompileAddr
|
||||
|
||||
signer := types.MakeSigner(evm.ChainConfig(), evm.Context.BlockNumber, evm.Context.Time)
|
||||
|
||||
from, err := types.Sender(signer, tx)
|
||||
|
|
@ -163,11 +162,21 @@ func (f *Firehose) CaptureTxStart(evm *vm.EVM, tx *types.Transaction) {
|
|||
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()
|
||||
|
||||
f.transaction = &pbeth.TransactionTrace{
|
||||
BeginOrdinal: f.blockOrdinal.Next(),
|
||||
Hash: tx.Hash().Bytes(),
|
||||
Hash: hash.Bytes(),
|
||||
From: from.Bytes(),
|
||||
To: to.Bytes(),
|
||||
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) {
|
||||
// FIXME: Re-implement by actualling callin `OnBlockStart/OnTrxStart/CaptureStart` etc.
|
||||
block := &pbeth.Block{
|
||||
Hash: b.Hash().Bytes(),
|
||||
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
|
||||
})
|
||||
f.OnBlockStart(b, big.NewInt(0), nil, nil)
|
||||
f.captureTxStart(types.NewTx(&types.LegacyTx{}), emptyCommonHash, emptyCommonAddress, emptyCommonAddress, func(common.Address) bool { return false })
|
||||
f.CaptureStart(emptyCommonAddress, emptyCommonAddress, false, nil, 0, nil)
|
||||
|
||||
for _, addr := range sortedKeys(alloc) {
|
||||
account := alloc[addr]
|
||||
|
||||
rootCall.AccountCreations = append(rootCall.AccountCreations, &pbeth.AccountCreation{
|
||||
Account: addr.Bytes(),
|
||||
Ordinal: f.blockOrdinal.Next(),
|
||||
})
|
||||
f.OnNewAccount(addr)
|
||||
|
||||
rootCall.BalanceChanges = append(rootCall.BalanceChanges, &pbeth.BalanceChange{
|
||||
Address: addr.Bytes(),
|
||||
NewValue: firehoseBigIntFromNative(account.Balance),
|
||||
Reason: pbeth.BalanceChange_REASON_GENESIS_BALANCE,
|
||||
Ordinal: f.blockOrdinal.Next(),
|
||||
})
|
||||
if account.Balance != nil && account.Balance.Sign() != 0 {
|
||||
activeCall := f.callStack.Peek()
|
||||
activeCall.BalanceChanges = append(activeCall.BalanceChanges, f.newBalanceChange("genesis", addr, common.Big0, account.Balance, pbeth.BalanceChange_REASON_GENESIS_BALANCE))
|
||||
}
|
||||
|
||||
if len(account.Code) > 0 {
|
||||
rootCall.CodeChanges = append(rootCall.CodeChanges, &pbeth.CodeChange{
|
||||
Address: addr.Bytes(),
|
||||
NewCode: account.Code,
|
||||
NewHash: crypto.Keccak256(account.Code),
|
||||
Ordinal: f.blockOrdinal.Next(),
|
||||
})
|
||||
f.OnCodeChange(addr, emptyCommonHash, nil, common.BytesToHash(crypto.Keccak256(account.Code)), account.Code)
|
||||
}
|
||||
|
||||
if account.Nonce > 0 {
|
||||
rootCall.NonceChanges = append(rootCall.NonceChanges, &pbeth.NonceChange{
|
||||
Address: addr.Bytes(),
|
||||
OldValue: 0,
|
||||
NewValue: account.Nonce,
|
||||
Ordinal: f.blockOrdinal.Next(),
|
||||
})
|
||||
f.OnNonceChange(addr, 0, account.Nonce)
|
||||
}
|
||||
|
||||
// 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) {
|
||||
rootCall.StorageChanges = append(rootCall.StorageChanges, &pbeth.StorageChange{
|
||||
Address: addr.Bytes(),
|
||||
Key: key.Bytes(),
|
||||
NewValue: account.Storage[key].Bytes(),
|
||||
Ordinal: f.blockOrdinal.Next(),
|
||||
})
|
||||
f.OnStorageChange(addr, key, emptyCommonHash, account.Storage[key])
|
||||
}
|
||||
}
|
||||
|
||||
// Ordering matters here, we must set the end ordinal of the call before the transaction
|
||||
rootTrx.EndOrdinal = f.blockOrdinal.Next()
|
||||
|
||||
f.printBlockToFirehose(block)
|
||||
f.resetBlock()
|
||||
f.CaptureEnd(nil, 0, nil)
|
||||
f.CaptureTxEnd(&types.Receipt{
|
||||
Type: uint8(types.LegacyTxType),
|
||||
PostState: b.Root().Bytes(),
|
||||
Status: types.ReceiptStatusSuccessful,
|
||||
}, nil)
|
||||
f.OnBlockEnd(nil)
|
||||
}
|
||||
|
||||
type bytesGetter interface {
|
||||
|
|
@ -591,17 +536,7 @@ func (f *Firehose) OnBalanceChange(a common.Address, prev, new *big.Int, reason
|
|||
|
||||
f.ensureInBlockOrTrx()
|
||||
|
||||
change := &pbeth.BalanceChange{
|
||||
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))
|
||||
}
|
||||
change := f.newBalanceChange("tracer", a, prev, new, balanceChangeReasonFromChain(reason))
|
||||
|
||||
if f.inTransaction.Load() {
|
||||
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) {
|
||||
f.ensureInBlockAndInTrx()
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue