@@ -670,3 +670,216 @@ func makeTestReceipts(n int, nPerBlock int) []types.Receipts {
670
670
}
671
671
return allReceipts
672
672
}
673
+
674
+ type fullLogRLP struct {
675
+ Address common.Address
676
+ Topics []common.Hash
677
+ Data []byte
678
+ BlockNumber uint64
679
+ TxHash common.Hash
680
+ TxIndex uint
681
+ BlockHash common.Hash
682
+ Index uint
683
+ }
684
+
685
+ func newFullLogRLP (l * types.Log ) * fullLogRLP {
686
+ return & fullLogRLP {
687
+ Address : l .Address ,
688
+ Topics : l .Topics ,
689
+ Data : l .Data ,
690
+ BlockNumber : l .BlockNumber ,
691
+ TxHash : l .TxHash ,
692
+ TxIndex : l .TxIndex ,
693
+ BlockHash : l .BlockHash ,
694
+ Index : l .Index ,
695
+ }
696
+ }
697
+
698
+ // Tests that logs associated with a single block can be retrieved.
699
+ func TestReadLogs (t * testing.T ) {
700
+ db := NewMemoryDatabase ()
701
+
702
+ // Create a live block since we need metadata to reconstruct the receipt
703
+ tx1 := types .NewTransaction (1 , common .HexToAddress ("0x1" ), big .NewInt (1 ), 1 , big .NewInt (1 ), nil )
704
+ tx2 := types .NewTransaction (2 , common .HexToAddress ("0x2" ), big .NewInt (2 ), 2 , big .NewInt (2 ), nil )
705
+
706
+ body := & types.Body {Transactions : types.Transactions {tx1 , tx2 }}
707
+
708
+ // Create the two receipts to manage afterwards
709
+ receipt1 := & types.Receipt {
710
+ Status : types .ReceiptStatusFailed ,
711
+ CumulativeGasUsed : 1 ,
712
+ Logs : []* types.Log {
713
+ {Address : common .BytesToAddress ([]byte {0x11 })},
714
+ {Address : common .BytesToAddress ([]byte {0x01 , 0x11 })},
715
+ },
716
+ TxHash : tx1 .Hash (),
717
+ ContractAddress : common .BytesToAddress ([]byte {0x01 , 0x11 , 0x11 }),
718
+ GasUsed : 111111 ,
719
+ }
720
+ receipt1 .Bloom = types .CreateBloom (types.Receipts {receipt1 })
721
+
722
+ receipt2 := & types.Receipt {
723
+ PostState : common.Hash {2 }.Bytes (),
724
+ CumulativeGasUsed : 2 ,
725
+ Logs : []* types.Log {
726
+ {Address : common .BytesToAddress ([]byte {0x22 })},
727
+ {Address : common .BytesToAddress ([]byte {0x02 , 0x22 })},
728
+ },
729
+ TxHash : tx2 .Hash (),
730
+ ContractAddress : common .BytesToAddress ([]byte {0x02 , 0x22 , 0x22 }),
731
+ GasUsed : 222222 ,
732
+ }
733
+ receipt2 .Bloom = types .CreateBloom (types.Receipts {receipt2 })
734
+ receipts := []* types.Receipt {receipt1 , receipt2 }
735
+
736
+ hash := common .BytesToHash ([]byte {0x03 , 0x14 })
737
+ // Check that no receipt entries are in a pristine database
738
+ if rs := ReadReceipts (db , hash , 0 , params .TestChainConfig ); len (rs ) != 0 {
739
+ t .Fatalf ("non existent receipts returned: %v" , rs )
740
+ }
741
+ // Insert the body that corresponds to the receipts
742
+ WriteBody (db , hash , 0 , body )
743
+
744
+ // Insert the receipt slice into the database and check presence
745
+ WriteReceipts (db , hash , 0 , receipts )
746
+
747
+ logs := ReadLogs (db , hash , 0 )
748
+ if len (logs ) == 0 {
749
+ t .Fatalf ("no logs returned" )
750
+ }
751
+ if have , want := len (logs ), 2 ; have != want {
752
+ t .Fatalf ("unexpected number of logs returned, have %d want %d" , have , want )
753
+ }
754
+ if have , want := len (logs [0 ]), 2 ; have != want {
755
+ t .Fatalf ("unexpected number of logs[0] returned, have %d want %d" , have , want )
756
+ }
757
+ if have , want := len (logs [1 ]), 2 ; have != want {
758
+ t .Fatalf ("unexpected number of logs[1] returned, have %d want %d" , have , want )
759
+ }
760
+
761
+ // Fill in log fields so we can compare their rlp encoding
762
+ if err := types .Receipts (receipts ).DeriveFields (params .TestChainConfig , hash , 0 , body .Transactions ); err != nil {
763
+ t .Fatal (err )
764
+ }
765
+ for i , pr := range receipts {
766
+ for j , pl := range pr .Logs {
767
+ rlpHave , err := rlp .EncodeToBytes (newFullLogRLP (logs [i ][j ]))
768
+ if err != nil {
769
+ t .Fatal (err )
770
+ }
771
+ rlpWant , err := rlp .EncodeToBytes (newFullLogRLP (pl ))
772
+ if err != nil {
773
+ t .Fatal (err )
774
+ }
775
+ if ! bytes .Equal (rlpHave , rlpWant ) {
776
+ t .Fatalf ("receipt #%d: receipt mismatch: have %s, want %s" , i , hex .EncodeToString (rlpHave ), hex .EncodeToString (rlpWant ))
777
+ }
778
+ }
779
+ }
780
+ }
781
+
782
+ func TestDeriveLogFields (t * testing.T ) {
783
+ // Create a few transactions to have receipts for
784
+ to2 := common .HexToAddress ("0x2" )
785
+ to3 := common .HexToAddress ("0x3" )
786
+ txs := types.Transactions {
787
+ types .NewTx (& types.LegacyTx {
788
+ Nonce : 1 ,
789
+ Value : big .NewInt (1 ),
790
+ Gas : 1 ,
791
+ GasPrice : big .NewInt (1 ),
792
+ }),
793
+ types .NewTx (& types.LegacyTx {
794
+ To : & to2 ,
795
+ Nonce : 2 ,
796
+ Value : big .NewInt (2 ),
797
+ Gas : 2 ,
798
+ GasPrice : big .NewInt (2 ),
799
+ }),
800
+ types .NewTx (& types.AccessListTx {
801
+ To : & to3 ,
802
+ Nonce : 3 ,
803
+ Value : big .NewInt (3 ),
804
+ Gas : 3 ,
805
+ GasPrice : big .NewInt (3 ),
806
+ }),
807
+ }
808
+ // Create the corresponding receipts
809
+ receipts := []* receiptLogs {
810
+ {
811
+ Logs : []* types.Log {
812
+ {Address : common .BytesToAddress ([]byte {0x11 })},
813
+ {Address : common .BytesToAddress ([]byte {0x01 , 0x11 })},
814
+ },
815
+ },
816
+ {
817
+ Logs : []* types.Log {
818
+ {Address : common .BytesToAddress ([]byte {0x22 })},
819
+ {Address : common .BytesToAddress ([]byte {0x02 , 0x22 })},
820
+ },
821
+ },
822
+ {
823
+ Logs : []* types.Log {
824
+ {Address : common .BytesToAddress ([]byte {0x33 })},
825
+ {Address : common .BytesToAddress ([]byte {0x03 , 0x33 })},
826
+ },
827
+ },
828
+ }
829
+
830
+ // Derive log metadata fields
831
+ number := big .NewInt (1 )
832
+ hash := common .BytesToHash ([]byte {0x03 , 0x14 })
833
+ if err := deriveLogFields (receipts , hash , number .Uint64 (), txs ); err != nil {
834
+ t .Fatal (err )
835
+ }
836
+
837
+ // Iterate over all the computed fields and check that they're correct
838
+ logIndex := uint (0 )
839
+ for i := range receipts {
840
+ for j := range receipts [i ].Logs {
841
+ if receipts [i ].Logs [j ].BlockNumber != number .Uint64 () {
842
+ t .Errorf ("receipts[%d].Logs[%d].BlockNumber = %d, want %d" , i , j , receipts [i ].Logs [j ].BlockNumber , number .Uint64 ())
843
+ }
844
+ if receipts [i ].Logs [j ].BlockHash != hash {
845
+ t .Errorf ("receipts[%d].Logs[%d].BlockHash = %s, want %s" , i , j , receipts [i ].Logs [j ].BlockHash .String (), hash .String ())
846
+ }
847
+ if receipts [i ].Logs [j ].TxHash != txs [i ].Hash () {
848
+ t .Errorf ("receipts[%d].Logs[%d].TxHash = %s, want %s" , i , j , receipts [i ].Logs [j ].TxHash .String (), txs [i ].Hash ().String ())
849
+ }
850
+ if receipts [i ].Logs [j ].TxIndex != uint (i ) {
851
+ t .Errorf ("receipts[%d].Logs[%d].TransactionIndex = %d, want %d" , i , j , receipts [i ].Logs [j ].TxIndex , i )
852
+ }
853
+ if receipts [i ].Logs [j ].Index != logIndex {
854
+ t .Errorf ("receipts[%d].Logs[%d].Index = %d, want %d" , i , j , receipts [i ].Logs [j ].Index , logIndex )
855
+ }
856
+ logIndex ++
857
+ }
858
+ }
859
+ }
860
+
861
+ func BenchmarkDecodeRLPLogs (b * testing.B ) {
862
+ // Encoded receipts from block 0x14ee094309fbe8f70b65f45ebcc08fb33f126942d97464aad5eb91cfd1e2d269
863
+ buf , err := ioutil .ReadFile ("testdata/stored_receipts.bin" )
864
+ if err != nil {
865
+ b .Fatal (err )
866
+ }
867
+ b .Run ("ReceiptForStorage" , func (b * testing.B ) {
868
+ b .ReportAllocs ()
869
+ var r []* types.ReceiptForStorage
870
+ for i := 0 ; i < b .N ; i ++ {
871
+ if err := rlp .DecodeBytes (buf , & r ); err != nil {
872
+ b .Fatal (err )
873
+ }
874
+ }
875
+ })
876
+ b .Run ("rlpLogs" , func (b * testing.B ) {
877
+ b .ReportAllocs ()
878
+ var r []* receiptLogs
879
+ for i := 0 ; i < b .N ; i ++ {
880
+ if err := rlp .DecodeBytes (buf , & r ); err != nil {
881
+ b .Fatal (err )
882
+ }
883
+ }
884
+ })
885
+ }
0 commit comments