@@ -4609,7 +4609,7 @@ func addNewFeeMarketCallContractTx(t testing.TB, contractAddress common.Address,
4609
4609
tx , _ = types .SignNewTx (testKey , signer , & types.LegacyTx {
4610
4610
Nonce : nonce ,
4611
4611
GasPrice : gasPrice ,
4612
- Gas : 150000 ,
4612
+ Gas : 160000 ,
4613
4613
To : & contractAddress ,
4614
4614
Data : data ,
4615
4615
})
@@ -4760,3 +4760,173 @@ func BenchmarkSatoshiFeeMarket(b *testing.B) {
4760
4760
b .StopTimer ()
4761
4761
}
4762
4762
}
4763
+
4764
+ func TestFullBlock (t * testing.T ) {
4765
+ // Set up logger to write to stdout at trace level
4766
+ // glogger := log.NewGlogHandler(log.NewTerminalHandler(os.Stdout, false))
4767
+ // glogger.Verbosity(log.LevelTrace)
4768
+ // log.SetDefault(log.NewLogger(glogger))
4769
+
4770
+ blockGasLimit := uint64 (50_000_000 )
4771
+
4772
+ // rewardRecipientMap[blockNumber][rewardRecipient] = numberOfTxs
4773
+ rewardRecipientMap := make (map [uint64 ]map [common.Address ]uint64 )
4774
+ remainingGasPoolMap := make (map [uint64 ]uint64 )
4775
+
4776
+ createGenRandomFn := func (withConfig bool ) func (* params.ChainConfig , * BlockChain , common.Address ) func (int , * BlockGen ) {
4777
+ return func (config * params.ChainConfig , chain * BlockChain , feeMarketAddress common.Address ) func (i int , gen * BlockGen ) {
4778
+ return func (i int , gen * BlockGen ) {
4779
+ signer := types .LatestSigner (config )
4780
+ fee := big .NewInt (1 )
4781
+
4782
+ gen .SetCoinbase (common.Address {1 })
4783
+
4784
+ blockNumber := gen .Number ().Uint64 ()
4785
+ rewardRecipientMap [blockNumber ] = make (map [common.Address ]uint64 )
4786
+
4787
+ for y := 0 ; gen .gasPool .Gas () > 500_000 ; y ++ {
4788
+ var counterContractAddress common.Address
4789
+ rewardRecipient := common .BytesToAddress (crypto .Keccak256 ([]byte (fmt .Sprintf ("recipient-%d" , y ))))
4790
+
4791
+ // Deploy counter contract
4792
+ nonce := gen .TxNonce (testAddr )
4793
+ _ , counterContractAddress = addNewFeeMarketTestContractTx (t , nonce , fee , chain , gen , signer )
4794
+
4795
+ // Add configuration only if enabled
4796
+ if withConfig {
4797
+ addFeeMarketConfigurationTx (t , feeMarketAddress , counterContractAddress , rewardRecipient , gen .TxNonce (testAddr ), fee , chain , gen , signer )
4798
+ }
4799
+
4800
+ // Add transactions until the block is full
4801
+ for z := 0 ; gen .gasPool .Gas () > 500_000 && z < 4 ; z ++ {
4802
+ addNewFeeMarketCallContractTx (t , counterContractAddress , gen .TxNonce (testAddr ), fee , chain , gen , signer )
4803
+ rewardRecipientMap [blockNumber ][rewardRecipient ]++
4804
+ }
4805
+ }
4806
+
4807
+ remainingGasPoolMap [blockNumber ] = gen .gasPool .Gas ()
4808
+ }
4809
+ }
4810
+ }
4811
+
4812
+ chainTesterFn := func (withConfig bool ) func (chain * BlockChain , blocks []* types.Block ) {
4813
+ return func (chain * BlockChain , blocks []* types.Block ) {
4814
+ stateDB , err := chain .State ()
4815
+ if err != nil {
4816
+ t .Fatalf ("failed to get state: %v" , err )
4817
+ }
4818
+
4819
+ for _ , block := range blocks {
4820
+ // txs := block.Transactions()
4821
+ receipts := chain .GetReceiptsByHash (block .Hash ())
4822
+
4823
+ fmt .Println ("Block number:" , block .Number ().Uint64 (), "txs:" , len (receipts ), "withConfig:" , withConfig )
4824
+
4825
+ // Calculate full gas used from receipts
4826
+ txGasUsed := uint64 (0 )
4827
+ for _ , receipt := range receipts {
4828
+ // tx := txs[idx]
4829
+ // fmt.Println("receipt:", "gasUsed:", receipt.GasUsed, "toAddr:", tx.To(), "status:", receipt.Status, "logs:", len(receipt.Logs), "contractAddr:", receipt.ContractAddress, "effectiveGasPrice:", receipt.EffectiveGasPrice)
4830
+ txGasUsed += receipt .GasUsed
4831
+
4832
+ if receipt .Status == types .ReceiptStatusFailed {
4833
+ t .Errorf ("transaction failed tx_hash: %s, status: %d, block number: %d" , receipt .TxHash .Hex (), receipt .Status , block .Number ().Uint64 ())
4834
+ }
4835
+ }
4836
+
4837
+ // Check if block gas used reports the sum of all txs gas used
4838
+ if block .GasUsed () != txGasUsed {
4839
+ t .Fatalf ("block.GasUsed() %d doesn't match txGasUsed %d" , block .GasUsed (), txGasUsed )
4840
+ }
4841
+
4842
+ // Calculate the total amount of fees paid as fee market rewards
4843
+ distributedAmount := big .NewInt (0 )
4844
+ if withConfig {
4845
+ blockRecepients := rewardRecipientMap [block .Number ().Uint64 ()]
4846
+ for recipient , numberOfTxs := range blockRecepients {
4847
+ // TODO: make gas 100000 configurable
4848
+ expect := new (big.Int ).Mul (big .NewInt (int64 (numberOfTxs )), big .NewInt (int64 (100000 )))
4849
+
4850
+ distributedAmount .Add (distributedAmount , expect )
4851
+
4852
+ actual := stateDB .GetBalance (recipient )
4853
+ require .Equal (t , actual .Uint64 (), expect .Uint64 (),
4854
+ fmt .Sprintf ("recipient (%s) balance %d is different that expected fee market reward %d (numberOfTxs: %d)" , recipient .Hex (), actual .Uint64 (), expect .Uint64 (), numberOfTxs ))
4855
+ }
4856
+ }
4857
+
4858
+ // Check if validator reward receives:
4859
+ // - all txs profit if there is no fee market configuration
4860
+ // - txs profit excluding the fee market rewards if there is a fee market configuration
4861
+ validatorRewardU64 := stateDB .GetBalance (params .SystemAddress ).Uint64 ()
4862
+ if withConfig {
4863
+ if validatorRewardU64 == txGasUsed {
4864
+ t .Errorf ("validator (%d) shouldn't receive all txs fees, as some has been distributed to fee market recipients (txGasUsed: %d)" , validatorRewardU64 , txGasUsed )
4865
+ }
4866
+ } else {
4867
+ if validatorRewardU64 != txGasUsed {
4868
+ t .Errorf ("validator (%d) should receive all txs fees" , validatorRewardU64 )
4869
+ }
4870
+ }
4871
+
4872
+ // Get the remaining gas in the pool
4873
+ remainingBlockPoolGas := remainingGasPoolMap [block .Number ().Uint64 ()]
4874
+ distributedAmountU64 := distributedAmount .Uint64 ()
4875
+
4876
+ // Check if block gas pool expands as expected to fit more transactions when distributed gas exists (aka ghost gas)
4877
+ if withConfig {
4878
+ if txGasUsed - distributedAmountU64 + remainingBlockPoolGas != blockGasLimit {
4879
+ t .Fatalf ("block gas limit %d doesn't fit txGasUsed %d, with included distributed gas %d" , blockGasLimit , txGasUsed , distributedAmountU64 )
4880
+ }
4881
+ } else {
4882
+ if txGasUsed + remainingBlockPoolGas != blockGasLimit {
4883
+ t .Fatalf ("block gas limit %d with remaining gas %d is not equal to txGasUsed %d" , blockGasLimit , remainingBlockPoolGas , txGasUsed )
4884
+ }
4885
+ }
4886
+ }
4887
+ t .Fail ()
4888
+ }
4889
+ }
4890
+
4891
+ t .Run ("WithConfiguration" , func (t * testing.T ) {
4892
+ testFeeMarketBlock (t , blockGasLimit , createGenRandomFn (true ), chainTesterFn (true ))
4893
+ })
4894
+
4895
+ t .Run ("WithoutConfiguration" , func (t * testing.T ) {
4896
+ testFeeMarketBlock (t , blockGasLimit , createGenRandomFn (false ), chainTesterFn (false ))
4897
+ })
4898
+ }
4899
+
4900
+ func testFeeMarketBlock (t * testing.T , gasLimit uint64 , genFn func (config * params.ChainConfig , chain * BlockChain , feeMarketAddress common.Address ) func (i int , gen * BlockGen ), chainTesterFn func (chain * BlockChain , blocks []* types.Block )) {
4901
+ config := params .SatoshiTestChainConfig
4902
+ gspec := & Genesis {
4903
+ Config : config ,
4904
+ GasLimit : gasLimit ,
4905
+ Alloc : types.GenesisAlloc {
4906
+ testAddr : {Balance : new (big.Int ).SetUint64 (15 * params .Ether )},
4907
+ },
4908
+ }
4909
+
4910
+ feeMarketAddress , feeMarketAccount := getFeeMarketGenesisAlloc (2 , 2 , 1000000 )
4911
+ gspec .Alloc [feeMarketAddress ] = feeMarketAccount
4912
+
4913
+ // Initialize blockchain
4914
+ frdir := t .TempDir ()
4915
+ db , err := rawdb .NewDatabaseWithFreezer (rawdb .NewMemoryDatabase (), frdir , "" , false , false , false , false , false )
4916
+ if err != nil {
4917
+ t .Fatalf ("failed to create database with ancient backend" )
4918
+ }
4919
+ engine := & mockSatoshi {}
4920
+ chain , _ := NewBlockChain (db , nil , gspec , nil , engine , vm.Config {}, nil , nil )
4921
+
4922
+ // Generate chain blocks
4923
+ _ , bs , _ := GenerateChainWithGenesis (gspec , engine , 1 , genFn (config , chain , feeMarketAddress ))
4924
+
4925
+ // Insert chain
4926
+ if _ , err := chain .InsertChain (bs ); err != nil {
4927
+ t .Fatalf ("failed to insert chain: %v" , err )
4928
+ }
4929
+
4930
+ // Verify the chain
4931
+ chainTesterFn (chain , bs )
4932
+ }
0 commit comments