@@ -27,11 +27,14 @@ import (
2727 "github.com/XinFinOrg/XDPoSChain/accounts/abi/bind"
2828 "github.com/XinFinOrg/XDPoSChain/accounts/abi/bind/backends"
2929 "github.com/XinFinOrg/XDPoSChain/common"
30+ "github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
3031 "github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
3132 "github.com/XinFinOrg/XDPoSChain/contracts/blocksigner"
33+ "github.com/XinFinOrg/XDPoSChain/core/rawdb"
3234 "github.com/XinFinOrg/XDPoSChain/core/types"
3335 "github.com/XinFinOrg/XDPoSChain/crypto"
3436 "github.com/XinFinOrg/XDPoSChain/params"
37+ "github.com/XinFinOrg/XDPoSChain/trie"
3538)
3639
3740var (
@@ -53,6 +56,50 @@ func getCommonBackend() *backends.SimulatedBackend {
5356 return backend
5457}
5558
59+ type rewardReplayChain struct {
60+ config * params.ChainConfig
61+ current * types.Header
62+ headers map [uint64 ]* types.Header
63+ blocks map [uint64 ]* types.Block
64+ }
65+
66+ func (c * rewardReplayChain ) Config () * params.ChainConfig {
67+ return c .config
68+ }
69+
70+ func (c * rewardReplayChain ) CurrentHeader () * types.Header {
71+ return c .current
72+ }
73+
74+ func (c * rewardReplayChain ) GetHeader (hash common.Hash , number uint64 ) * types.Header {
75+ header := c .headers [number ]
76+ if header == nil || header .Hash () != hash {
77+ return nil
78+ }
79+ return header
80+ }
81+
82+ func (c * rewardReplayChain ) GetHeaderByNumber (number uint64 ) * types.Header {
83+ return c .headers [number ]
84+ }
85+
86+ func (c * rewardReplayChain ) GetHeaderByHash (hash common.Hash ) * types.Header {
87+ for _ , header := range c .headers {
88+ if header .Hash () == hash {
89+ return header
90+ }
91+ }
92+ return nil
93+ }
94+
95+ func (c * rewardReplayChain ) GetBlock (hash common.Hash , number uint64 ) * types.Block {
96+ block := c .blocks [number ]
97+ if block == nil || block .Hash () != hash {
98+ return nil
99+ }
100+ return block
101+ }
102+
56103func TestSendTxSign (t * testing.T ) {
57104 accounts := []common.Address {acc2Addr , acc3Addr , acc4Addr }
58105 keys := []* ecdsa.PrivateKey {acc2Key , acc3Key , acc4Key }
@@ -116,6 +163,109 @@ func TestSendTxSign(t *testing.T) {
116163 }
117164}
118165
166+ func TestGetRewardForCheckpointReplaysSigningTxsFromRawReceipts (t * testing.T ) {
167+ database := rawdb .NewMemoryDatabase ()
168+ config := params .TestXDPoSMockChainConfig
169+ engine := XDPoS .New (config , database )
170+
171+ checkpointExtra := append (bytes .Repeat ([]byte {0x00 }, utils .ExtraVanity ), acc1Addr .Bytes ()... )
172+ checkpointExtra = append (checkpointExtra , make ([]byte , utils .ExtraSeal )... )
173+
174+ checkpointHeader := types .NewBlock (& types.Header {
175+ Number : big .NewInt (14 ),
176+ Extra : checkpointExtra ,
177+ }, nil , nil , nil , trie .NewStackTrie (nil ))
178+ block15 := types .NewBlock (& types.Header {
179+ Number : big .NewInt (15 ),
180+ ParentHash : checkpointHeader .Hash (),
181+ }, nil , nil , nil , trie .NewStackTrie (nil ))
182+ block16 := types .NewBlock (& types.Header {
183+ Number : big .NewInt (16 ),
184+ ParentHash : block15 .Hash (),
185+ }, nil , nil , nil , trie .NewStackTrie (nil ))
186+
187+ signer := types .MakeSigner (config , big .NewInt (17 ))
188+ signingTx1 , err := types .SignTx (CreateTxSign (big .NewInt (15 ), block15 .Hash (), 0 , common .BlockSignersBinary ), signer , acc1Key )
189+ if err != nil {
190+ t .Fatalf ("failed to sign first replay tx: %v" , err )
191+ }
192+ receipts := []* types.Receipt {
193+ {Status : types .ReceiptStatusSuccessful , CumulativeGasUsed : 200000 , TxHash : signingTx1 .Hash ()},
194+ }
195+ replayBlock := types .NewBlock (& types.Header {
196+ Number : big .NewInt (17 ),
197+ ParentHash : block16 .Hash (),
198+ }, []* types.Transaction {signingTx1 }, nil , receipts , trie .NewStackTrie (nil ))
199+ rawdb .WriteReceipts (database , replayBlock .Hash (), replayBlock .NumberU64 (), receipts )
200+
201+ rawReceipts := rawdb .ReadRawReceipts (database , replayBlock .Hash (), replayBlock .NumberU64 ())
202+ if len (rawReceipts ) != 1 {
203+ t .Fatalf ("unexpected raw receipt count: have %d want 1" , len (rawReceipts ))
204+ }
205+ if rawReceipts [0 ].TxHash != (common.Hash {}) {
206+ t .Fatalf ("expected raw receipt without TxHash metadata, got %s" , rawReceipts [0 ].TxHash )
207+ }
208+ precheckCached := engine .CacheNoneTIPSigningTxs (replayBlock .Header (), replayBlock .Transactions (), rawReceipts )
209+ if len (precheckCached ) != 1 {
210+ t .Fatalf ("unexpected cached signing tx count from raw receipts: have %d want 1" , len (precheckCached ))
211+ }
212+ if from := precheckCached [0 ].From (); from == nil || * from != acc1Addr {
213+ t .Fatalf ("unexpected signer recovered from replay tx: have %v want %s" , from , acc1Addr )
214+ }
215+ if got := common .BytesToHash (precheckCached [0 ].Data ()[len (precheckCached [0 ].Data ())- 32 :]); got != block15 .Hash () {
216+ t .Fatalf ("unexpected first replay target hash: have %s want %s" , got , block15 .Hash ())
217+ }
218+ masternodes := engine .GetMasternodesFromCheckpointHeader (checkpointHeader .Header ())
219+ if len (masternodes ) != 1 || masternodes [0 ] != acc1Addr {
220+ t .Fatalf ("unexpected checkpoint masternodes: have %v want [%s]" , masternodes , acc1Addr )
221+ }
222+
223+ checkpointBlock := types .NewBlock (& types.Header {
224+ Number : big .NewInt (18 ),
225+ ParentHash : replayBlock .Hash (),
226+ }, nil , nil , nil , trie .NewStackTrie (nil ))
227+ engine = XDPoS .New (config , database )
228+ chain := & rewardReplayChain {
229+ config : config ,
230+ current : checkpointBlock .Header (),
231+ headers : map [uint64 ]* types.Header {
232+ 14 : checkpointHeader .Header (),
233+ 15 : block15 .Header (),
234+ 16 : block16 .Header (),
235+ 17 : replayBlock .Header (),
236+ 18 : checkpointBlock .Header (),
237+ },
238+ blocks : map [uint64 ]* types.Block {
239+ 15 : block15 ,
240+ 16 : block16 ,
241+ 17 : replayBlock ,
242+ 18 : checkpointBlock ,
243+ },
244+ }
245+ if _ , ok := engine .GetCachedSigningTxs (replayBlock .Hash ()); ok {
246+ t .Fatal ("expected empty signing cache before restart replay" )
247+ }
248+
249+ totalSigner := uint64 (0 )
250+ signers , err := GetRewardForCheckpoint (engine , chain , checkpointBlock .Header (), 2 , & totalSigner )
251+ if err != nil {
252+ t .Fatalf ("GetRewardForCheckpoint returned error: %v" , err )
253+ }
254+ if cached , ok := engine .GetCachedSigningTxs (replayBlock .Hash ()); ! ok || len (cached ) != 1 {
255+ t .Fatalf ("expected replay block signing txs to be cached during reward replay, got ok=%v len=%d" , ok , len (cached ))
256+ }
257+ if totalSigner != 1 {
258+ t .Fatalf ("unexpected total signer count: have %d want 1" , totalSigner )
259+ }
260+ rewardLog := signers [acc1Addr ]
261+ if rewardLog == nil {
262+ t .Fatalf ("expected signer %s to be reconstructed from replay" , acc1Addr )
263+ }
264+ if rewardLog .Sign != 1 {
265+ t .Fatalf ("unexpected signer count for %s: have %d want 1" , acc1Addr , rewardLog .Sign )
266+ }
267+ }
268+
119269// Generate random string.
120270func randomHash () common.Hash {
121271 letterBytes := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789"
0 commit comments