all: 4844 devnet 6 integration

This commit is contained in:
Marius van der Wijden 2023-05-26 12:00:09 +02:00 committed by lightclient
parent cde462c6bf
commit 7dba16c886
No known key found for this signature in database
GPG key ID: 75C916AFEE20183E
20 changed files with 281 additions and 22 deletions

View file

@ -379,6 +379,14 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
return nil, errors.New("withdrawals set before Shanghai activation")
}
}
if chain.Config().IsCancun(header.Number, header.Time) {
var blobs int
for _, tx := range txs {
blobs += len(tx.BlobHashes())
}
blobGasUsed := uint64(blobs * params.BlobTxBlobGasPerBlob)
header.BlobGasUsed = &blobGasUsed
}
// Finalize and assemble the block.
beacon.Finalize(chain, header, state, txs, uncles, withdrawals)

View file

@ -45,8 +45,8 @@ func TestCalcExcessBlobGas(t *testing.T) {
// The excess blob gas should decrease by however much the target was
// under-shot, capped at zero.
{params.BlobTxTargetBlobGasPerBlock, params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob, params.BlobTxTargetBlobGasPerBlock},
{params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, params.BlobTxBlobGasPerBlob},
{params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 2, 0},
{params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, 2 * params.BlobTxBlobGasPerBlob},
{params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 2, params.BlobTxBlobGasPerBlob},
{params.BlobTxBlobGasPerBlob - 1, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, 0},
}
for _, tt := range tests {
@ -64,8 +64,9 @@ func TestCalcBlobFee(t *testing.T) {
}{
{0, 1},
{1542706, 1},
{1542707, 2},
{10 * 1024 * 1024, 111},
{1542707, 1},
{3085414, 2},
{10 * 1024 * 1024, 23},
}
for i, tt := range tests {
have := CalcBlobFee(tt.excessBlobGas)

View file

@ -496,6 +496,14 @@ func (g *Genesis) ToBlock() *types.Block {
}
}
}
if g.Config != nil && g.Config.IsCancun(big.NewInt(int64(g.Number)), g.Timestamp) {
if g.ExcessBlobGas == nil {
var excessBlobGas uint64
head.ExcessBlobGas = &excessBlobGas
} else {
head.ExcessBlobGas = g.ExcessBlobGas
}
}
return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil)).WithWithdrawals(withdrawals)
}

View file

@ -954,6 +954,8 @@ func (p *BlobPool) reinject(addr common.Address, txhash common.Hash) {
}
p.lookup[meta.hash] = meta.id
p.stored += uint64(meta.size)
p.eventFeed.Send(core.NewTxsEvent{Txs: types.Transactions{tx}})
}
// SetGasTip implements txpool.SubPool, allowing the blob pool's gas requirements
@ -1036,7 +1038,6 @@ func (p *BlobPool) validateTx(tx *types.Transaction) error {
// Ensure the transaction adheres to the stateful pool filters (nonce, balance)
stateOpts := &txpool.ValidationOptionsWithState{
State: p.state,
FirstNonceGap: func(addr common.Address) uint64 {
// Nonce gaps are not permitted in the blob pool, the first gap will
// be the next nonce shifted by however many transactions we already
@ -1297,6 +1298,7 @@ func (p *BlobPool) add(tx *types.Transaction) (err error) {
}
p.updateStorageMetrics()
p.eventFeed.Send(core.NewTxsEvent{Txs: types.Transactions{tx}})
return nil
}

View file

@ -46,6 +46,8 @@ func TestNewSlotter(t *testing.T) {
10*blobSize + txAvgSize, // 1-4 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
11*blobSize + txAvgSize, // 1-4 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
12*blobSize + txAvgSize, // 1-4 blobs + unexpectedly large tx infos >= 4 blobs + max tx metadata size
13*blobSize + txAvgSize, // 1-4 blobs + unexpectedly large tx infos >= 4 blobs + max tx metadata size
14*blobSize + txAvgSize, // 1-4 blobs + unexpectedly large tx infos >= 4 blobs + max tx metadata size
}
if len(shelves) != len(want) {
t.Errorf("shelves count mismatch: have %d, want %d", len(shelves), len(want))

File diff suppressed because one or more lines are too long

View file

@ -1287,7 +1287,11 @@ func testTransactionFetcher(t *testing.T, tt txFetcherTest) {
}
case doTxEnqueue:
if err := fetcher.Enqueue(step.peer, step.txs, step.direct); err != nil {
var txs []*types.BlobTxWithBlobs
for _, tx := range step.txs {
txs = append(txs, types.NewBlobTxWithBlobs(tx, nil, nil, nil))
}
if err := fetcher.Enqueue(step.peer, txs, step.direct); err != nil {
t.Errorf("step %d: %v", i, err)
}
<-wait // Fetcher needs to process this, wait until it's done

View file

@ -625,7 +625,7 @@ func (h *handler) BroadcastTransactions(txs types.Transactions) {
peers := h.peers.peersWithoutTransaction(tx.Hash())
var numDirect int
if tx.Size() <= txMaxBroadcastSize {
if tx.Size() <= txMaxBroadcastSize && tx.Type() != types.BlobTxType {
numDirect = int(math.Sqrt(float64(len(peers))))
}
// Send the tx unconditionally to a subset of our peers

View file

@ -30,12 +30,14 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256"
)
// testEthHandler is a mock event handler to listen for inbound network requests
@ -71,7 +73,11 @@ func (h *testEthHandler) Handle(peer *eth.Peer, packet eth.Packet) error {
return nil
case *eth.PooledTransactionsPacket:
h.txBroadcasts.Send(([]*types.Transaction)(*packet))
var txs []*types.Transaction
for _, tx := range *packet {
txs = append(txs, tx.Transaction)
}
h.txBroadcasts.Send(txs)
return nil
default:
@ -454,6 +460,87 @@ func testTransactionPropagation(t *testing.T, protocol uint) {
}
}
func TestBlobTransactionPropagation68(t *testing.T) { testBlobTransactionPropagation(t, eth.ETH68) }
func testBlobTransactionPropagation(t *testing.T, protocol uint) {
t.Parallel()
// Create a source handler to send transactions from and a number of sinks
// to receive them. We need multiple sinks since a one-to-one peering would
// broadcast all transactions without announcement.
source := newTestHandler()
source.handler.snapSync.Store(false) // Avoid requiring snap, otherwise some will be dropped below
defer source.close()
sinks := make([]*testHandler, 10)
for i := 0; i < len(sinks); i++ {
sinks[i] = newTestHandler()
defer sinks[i].close()
sinks[i].handler.acceptTxs.Store(true) // mark synced to accept transactions
}
// Interconnect all the sink handlers with the source handler
for i, sink := range sinks {
sink := sink // Closure for gorotuine below
sourcePipe, sinkPipe := p2p.MsgPipe()
defer sourcePipe.Close()
defer sinkPipe.Close()
sourcePeer := eth.NewPeer(protocol, p2p.NewPeerPipe(enode.ID{byte(i + 1)}, "", nil, sourcePipe), sourcePipe, source.txpool)
sinkPeer := eth.NewPeer(protocol, p2p.NewPeerPipe(enode.ID{0}, "", nil, sinkPipe), sinkPipe, sink.txpool)
defer sourcePeer.Close()
defer sinkPeer.Close()
go source.handler.runEthPeer(sourcePeer, func(peer *eth.Peer) error {
return eth.Handle((*ethHandler)(source.handler), peer)
})
go sink.handler.runEthPeer(sinkPeer, func(peer *eth.Peer) error {
return eth.Handle((*ethHandler)(sink.handler), peer)
})
}
// Subscribe to all the transaction pools
txChs := make([]chan core.NewTxsEvent, len(sinks))
for i := 0; i < len(sinks); i++ {
txChs[i] = make(chan core.NewTxsEvent, 1024)
sub := sinks[i].txpool.SubscribeNewTxsEvent(txChs[i])
defer sub.Unsubscribe()
}
// Fill the source pool with transactions and wait for them at the sinks
txs := make([]*txpool.Transaction, 1024)
for nonce := range txs {
tx := types.NewTx(&types.BlobTx{
Nonce: uint64(nonce),
To: common.Address{},
GasTipCap: uint256.NewInt(0),
GasFeeCap: uint256.NewInt(0),
Gas: 100000,
Value: uint256.NewInt(0),
BlobHashes: make([]common.Hash, 1),
ChainID: uint256.NewInt(0),
Data: nil,
})
tx, _ = types.SignTx(tx, types.NewCancunSigner(common.Big0), testKey)
txs[nonce] = &txpool.Transaction{Tx: tx, BlobTxBlobs: make([]kzg4844.Blob, 1), BlobTxCommits: make([]kzg4844.Commitment, 1), BlobTxProofs: make([]kzg4844.Proof, 1)}
}
source.txpool.Add(txs, false, false)
// Iterate through all the sinks and ensure they all got the transactions
for i := range sinks {
for arrived, timeout := 0, false; arrived < len(txs) && !timeout; {
select {
case event := <-txChs[i]:
arrived += len(event.Txs)
case <-time.After(2 * time.Second):
t.Errorf("sink %d: transaction propagation timed out: have %d, want %d", i, arrived, len(txs))
timeout = true
}
}
}
}
// Tests that blocks are broadcast to a sqrt number of peers only.
func TestBroadcastBlock1Peer(t *testing.T) { testBroadcastBlock(t, 1, 1) }
func TestBroadcastBlock2Peers(t *testing.T) { testBroadcastBlock(t, 2, 1) }

View file

@ -80,6 +80,7 @@ func (p *Peer) broadcastTransactions() {
size common.StorageSize
)
for i := 0; i < len(queue) && size < maxTxPacketSize; i++ {
// Do not broadcast blob transactions
if tx := p.txpool.Get(queue[i]); tx != nil {
txs = append(txs, tx)
size += common.StorageSize(tx.Size())

File diff suppressed because one or more lines are too long

View file

@ -108,7 +108,7 @@ func TestEth66EmptyMessages(t *testing.T) {
ReceiptsPacket66{1111, ReceiptsPacket([][]*types.Receipt{})},
// Transactions
GetPooledTransactionsPacket66{1111, GetPooledTransactionsPacket([]common.Hash{})},
PooledTransactionsPacket66{1111, PooledTransactionsPacket([]*types.Transaction{})},
PooledTransactionsPacket66{1111, PooledTransactionsPacket([]*types.BlobTxWithBlobs{})},
PooledTransactionsRLPPacket66{1111, PooledTransactionsRLPPacket([]rlp.RawValue{})},
} {
if have, _ := rlp.EncodeToBytes(msg); !bytes.Equal(have, want) {
@ -125,6 +125,7 @@ func TestEth66Messages(t *testing.T) {
blockBody *BlockBody
blockBodyRlp rlp.RawValue
txs []*types.Transaction
poolTxs []*types.BlobTxWithBlobs
txRlps []rlp.RawValue
hashes []common.Hash
receipts []*types.Receipt
@ -153,6 +154,7 @@ func TestEth66Messages(t *testing.T) {
}
txs = append(txs, tx)
txRlps = append(txRlps, rlpdata)
poolTxs = append(poolTxs, types.NewBlobTxWithBlobs(tx, nil, nil, nil))
}
}
// init the block body data, both object and rlp form
@ -251,7 +253,7 @@ func TestEth66Messages(t *testing.T) {
common.FromHex("f847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef"),
},
{
PooledTransactionsPacket66{1111, PooledTransactionsPacket(txs)},
PooledTransactionsPacket66{1111, PooledTransactionsPacket(poolTxs)},
common.FromHex("f8d7820457f8d2f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb"),
},
{

2
go.sum
View file

@ -88,6 +88,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHH
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/crate-crypto/go-ipa v0.0.0-20230601170251-1830d0757c80 h1:DuBDHVjgGMPki7bAyh91+3cF1Vh34sAEdH8JQgbc2R0=
github.com/crate-crypto/go-ipa v0.0.0-20230601170251-1830d0757c80/go.mod h1:gzbVz57IDJgQ9rLQwfSk696JGWof8ftznEL9GoAv3NI=
github.com/crate-crypto/go-kzg-4844 v0.2.0 h1:UVuHOE+5tIWrim4zf/Xaa43+MIsDCPyW76QhUpiMGj4=
github.com/crate-crypto/go-kzg-4844 v0.2.0/go.mod h1:SBP7ikXEgDnUPONgm33HtuDZEDtWa3L4QtN1ocJSEQ4=
github.com/crate-crypto/go-kzg-4844 v0.3.0 h1:UBlWE0CgyFqqzTI+IFyCzA7A3Zw4iip6uzRv5NIXG0A=
github.com/crate-crypto/go-kzg-4844 v0.3.0/go.mod h1:SBP7ikXEgDnUPONgm33HtuDZEDtWa3L4QtN1ocJSEQ4=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=

View file

@ -1310,8 +1310,7 @@ func (r *Resolver) SendRawTransaction(ctx context.Context, args struct{ Data hex
if err := tx.UnmarshalBinary(args.Data); err != nil {
return common.Hash{}, err
}
hash, err := ethapi.SubmitTransaction(ctx, r.backend, tx)
return hash, err
return ethapi.SubmitTransaction(ctx, r.backend, tx)
}
// FilterCriteria encapsulates the arguments to `logs` on the root resolver object.

View file

@ -1858,6 +1858,7 @@ func SubmitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (c
if err := b.SendTx(ctx, tx); err != nil {
return common.Hash{}, err
}
// Print a log with full tx details for manual investigations and interventions
head := b.CurrentBlock()
signer := types.MakeSigner(b.ChainConfig(), head.Number, head.Time)
@ -1928,6 +1929,9 @@ func (s *TransactionAPI) FillTransaction(ctx context.Context, args TransactionAr
// The sender is responsible for signing the transaction and using the correct nonce.
func (s *TransactionAPI) SendRawTransaction(ctx context.Context, input hexutil.Bytes) (common.Hash, error) {
tx := new(types.Transaction)
if len(input) < 1 {
return common.Hash{}, errors.New("input to short")
}
if err := tx.UnmarshalBinary(input); err != nil {
return common.Hash{}, err
}

View file

@ -43,6 +43,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/internal/blocktest"
@ -560,6 +561,9 @@ func (b testBackend) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) even
func (b testBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
panic("implement me")
}
func (b testBackend) SendBlobTx(ctx context.Context, signedTx *types.Transaction, blobTxBlobs []kzg4844.Blob, blobTxCommits []kzg4844.Commitment, blobTxProofs []kzg4844.Proof) error {
panic("implement me")
}
func (b testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
tx, blockHash, blockNumber, index := rawdb.ReadTransaction(b.db, txHash)
return tx, blockHash, blockNumber, index, nil

View file

@ -75,6 +75,7 @@ type Backend interface {
// Transaction pool API
SendTx(ctx context.Context, signedTx *types.Transaction) error
GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
GetPoolTransactions() (types.Transactions, error)
GetPoolTransaction(txHash common.Hash) *types.Transaction

View file

@ -34,6 +34,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
@ -316,6 +317,9 @@ func (b *backendMock) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) eve
return nil
}
func (b *backendMock) SendTx(ctx context.Context, signedTx *types.Transaction) error { return nil }
func (b *backendMock) SendBlobTx(ctx context.Context, signedTx *types.Transaction, blobTxBlobs []kzg4844.Blob, blobTxCommits []kzg4844.Commitment, blobTxProofs []kzg4844.Proof) error {
return nil
}
func (b *backendMock) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
return nil, [32]byte{}, 0, 0, nil
}

View file

@ -32,6 +32,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/eth/gasprice"
"github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/ethdb"
@ -199,6 +200,10 @@ func (b *LesApiBackend) SendTx(ctx context.Context, signedTx *types.Transaction)
return b.eth.txPool.Add(ctx, signedTx)
}
func (b *LesApiBackend) SendBlobTx(ctx context.Context, signedTx *types.Transaction, blobTxBlobs []kzg4844.Blob, blobTxCommits []kzg4844.Commitment, blobTxProofs []kzg4844.Proof) error {
return errors.New("blob transactions not implemented on LES")
}
func (b *LesApiBackend) RemoveTx(txHash common.Hash) {
b.eth.txPool.RemoveTx(txHash)
}

View file

@ -167,11 +167,11 @@ const (
BlobTxBytesPerFieldElement = 32 // Size in bytes of a field element
BlobTxFieldElementsPerBlob = 4096 // Number of field elements stored in a single data blob
BlobTxHashVersion = 0x01 // Version byte of the commitment hash
MaxBlobGasPerBlock = 1 << 19 // Maximum consumable blob gas for data blobs per block
BlobTxTargetBlobGasPerBlock = 1 << 18 // Target consumable blob gas for data blobs per block (for 1559-like pricing)
BlobTxBlobGasPerBlob = 1 << 17 // Gas consumption of a single data blob (== blob byte size)
MaxBlobGasPerBlock = 6 * BlobTxBlobGasPerBlob // Maximum consumable blob gas for data blobs per block
BlobTxTargetBlobGasPerBlock = 3 * BlobTxBlobGasPerBlob // Target consumable data gas for data blobs per block (for 1559-like pricing)
BlobTxMinBlobGasprice = 1 // Minimum gas price for data blobs
BlobTxBlobGaspriceUpdateFraction = 2225652 // Controls the maximum rate of change for blob gas price
BlobTxBlobGaspriceUpdateFraction = 3338477 // Controls the maximum rate of change for data gas price
BlobTxPointEvaluationPrecompileGas = 50000 // Gas price for the point evaluation precompile.
)