@@ -38,6 +38,8 @@ import (
3838 "github.com/ethereum/go-ethereum/ethdb"
3939 "github.com/ethereum/go-ethereum/event"
4040 "github.com/ethereum/go-ethereum/params"
41+ "github.com/holiman/uint256"
42+ "github.com/protolambda/ztyp/view"
4143)
4244
4345const (
@@ -198,6 +200,42 @@ func (b *testWorkerBackend) newRandomTx(creation bool) *types.Transaction {
198200 return tx
199201}
200202
203+ func (b * testWorkerBackend ) newRandomBlobTx (chainID * big.Int , nonce uint64 ) * types.Transaction {
204+ var blobs types.Blobs
205+ blobs = append (blobs , types.Blob {})
206+
207+ commitments , versionedHashes , aggregatedProof , err := blobs .ComputeCommitmentsAndAggregatedProof ()
208+ if err != nil {
209+ panic (err )
210+ }
211+
212+ gasPrice := big .NewInt (10 * params .InitialBaseFee ).Uint64 ()
213+ txData := & types.SignedBlobTx {
214+ Message : types.BlobTxMessage {
215+ ChainID : view .Uint256View (* uint256 .NewInt (chainID .Uint64 ())),
216+ Nonce : view .Uint64View (nonce ),
217+ Gas : view .Uint64View (testGas ),
218+ GasFeeCap : view .Uint256View (* uint256 .NewInt (gasPrice )),
219+ GasTipCap : view .Uint256View (* uint256 .NewInt (gasPrice )),
220+ Value : view .Uint256View (* uint256 .NewInt (1000 )),
221+ To : types.AddressOptionalSSZ {Address : (* types .AddressSSZ )(& testUserAddress )},
222+ BlobVersionedHashes : versionedHashes ,
223+ },
224+ }
225+ wrapData := & types.BlobTxWrapData {
226+ BlobKzgs : commitments ,
227+ Blobs : blobs ,
228+ KzgAggregatedProof : aggregatedProof ,
229+ }
230+ tx := types .NewTx (txData , types .WithTxWrapData (wrapData ))
231+ signer := types .NewDankSigner (chainID )
232+ tx , err = types .SignTx (tx , signer , testBankKey )
233+ if err != nil {
234+ panic (err )
235+ }
236+ return tx
237+ }
238+
201239func newTestWorker (t * testing.T , chainConfig * params.ChainConfig , engine consensus.Engine , db ethdb.Database , blocks int ) (* worker , * testWorkerBackend ) {
202240 backend := newTestWorkerBackend (t , chainConfig , engine , db , blocks )
203241 backend .txPool .AddLocals (pendingTxs )
@@ -670,3 +708,85 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co
670708 }
671709 }
672710}
711+
712+ func testGenerateBlockWithBlobsAndImport (t * testing.T , isClique bool ) {
713+ var (
714+ engine consensus.Engine
715+ chainConfig * params.ChainConfig
716+ db = rawdb .NewMemoryDatabase ()
717+ )
718+ if isClique {
719+ chainConfig = params .AllCliqueProtocolChanges
720+ chainConfig .Clique = & params.CliqueConfig {Period : 1 , Epoch : 30000 }
721+ engine = clique .New (chainConfig .Clique , db )
722+ } else {
723+ chainConfig = params .AllEthashProtocolChanges
724+ engine = ethash .NewFaker ()
725+ }
726+
727+ chainConfig .LondonBlock = big .NewInt (0 )
728+ chainConfig .ShardingForkBlock = big .NewInt (0 )
729+ w , b := newTestWorker (t , chainConfig , engine , db , 0 )
730+ defer w .close ()
731+
732+ // This test chain imports the mined blocks.
733+ db2 := rawdb .NewMemoryDatabase ()
734+ b .genesis .MustCommit (db2 )
735+ chain , _ := core .NewBlockChain (db2 , nil , b .chain .Config (), engine , vm.Config {}, nil , nil )
736+ defer chain .Stop ()
737+
738+ // Ignore empty commit here for less noise.
739+ w .skipSealHook = func (task * task ) bool {
740+ return len (task .receipts ) == 0
741+ }
742+
743+ // Wait for mined blocks.
744+ sub := w .mux .Subscribe (core.NewMinedBlockEvent {})
745+ defer sub .Unsubscribe ()
746+
747+ // Start mining!
748+ w .start ()
749+
750+ nonce := b .txPool .Nonce (testBankAddress )
751+
752+ var txs []* types.Transaction
753+ for i := 0 ; i < params .MaxBlobsPerBlock + 5 ; i ++ {
754+ txs = append (txs , b .newRandomBlobTx (chainConfig .ChainID , nonce ))
755+ nonce += 1
756+ }
757+ // Batch add blob txs to guarantee single block inclusion
758+ errs := b .txPool .AddLocals (txs )
759+ for i := range errs {
760+ if errs [i ] != nil {
761+ panic (errs [i ])
762+ }
763+ }
764+
765+ select {
766+ case ev := <- sub .Chan ():
767+ block := ev .Data .(core.NewMinedBlockEvent ).Block
768+ if _ , err := chain .InsertChain ([]* types.Block {block }); err != nil {
769+ t .Fatalf ("failed to insert new mined block %d: %v" , block .NumberU64 (), err )
770+ }
771+ txs := block .Transactions ()
772+ var numBlobs int
773+ for i := range txs {
774+ numBlobs += len (txs [i ].DataHashes ())
775+ }
776+ // Assert that there are no more than params.MaxBlobsPerBlock blobs in the block
777+ if numBlobs != params .MaxBlobsPerBlock {
778+ t .Fatalf ("unexpected number of blobs in block: %d" , numBlobs )
779+ }
780+
781+ case <- time .After (3 * time .Second ): // Worker needs 1s to include new changes.
782+ t .Fatalf ("timeout" )
783+ }
784+ }
785+
786+ func TestGenerateBlockWithBlobsAndImportEthash (t * testing.T ) {
787+ testGenerateBlockWithBlobsAndImport (t , false )
788+ }
789+
790+ func TestGenerateBlockWithBlobsAndImportClique (t * testing.T ) {
791+ testGenerateBlockWithBlobsAndImport (t , true )
792+ }
0 commit comments