4343import org .ethereum .core .TransactionPool ;
4444import org .ethereum .datasource .KeyValueDataSource ;
4545import org .ethereum .db .BlockStore ;
46+ import org .ethereum .util .ByteUtil ;
4647import org .ethereum .util .RLP ;
4748import org .ethereum .util .RLPElement ;
4849import org .ethereum .util .RLPList ;
@@ -78,7 +79,7 @@ public class SnapshotProcessor implements InternalService {
7879 private final Blockchain blockchain ;
7980 private final TrieStore trieStore ;
8081 private final KeyValueDataSource tmpSnapSyncKeyValueDataSource ;
81- public static final int TMP_NODES_SIZE_KEY = -1 ;
82+ private static final int TMP_NODES_SIZE_KEY = -1 ;
8283 private final BlockStore blockStore ;
8384 private final int chunkSize ;
8485 private final int checkpointDistance ;
@@ -649,12 +650,23 @@ private void processOrderedStateChunkResponse(SnapSyncState state, Peer peer, Sn
649650 }
650651
651652 if (trieElements .size () > 0 ) {
653+ final var existingNodesSizeInBytes = tmpSnapSyncKeyValueDataSource .get (ByteUtil .intToBytes (TMP_NODES_SIZE_KEY ));
654+ var existingNodesSize = 0 ;
655+
656+ if (existingNodesSizeInBytes != null ) {
657+ existingNodesSize = ByteUtil .byteArrayToInt (existingNodesSizeInBytes );
658+ }
659+
652660 for (int i = 0 ; i < trieElements .size (); i ++) {
653661 final RLPElement trieElement = trieElements .get (i );
654662 byte [] value = trieElement .getRLPData ();
655663 nodes .add (TrieDTO .decodeFromSync (value ));
664+
665+ tmpSnapSyncKeyValueDataSource .put (ByteUtil .intToBytes (existingNodesSize + i ), value );
656666 }
657667 nodes .get (0 ).setLeftHash (firstNodeLeftHash );
668+
669+ tmpSnapSyncKeyValueDataSource .put (ByteUtil .intToBytes (TMP_NODES_SIZE_KEY ), ByteUtil .intToBytes (nodes .size () + existingNodesSize ));
658670 }
659671
660672 if (lastNodeHashes .size () > 0 ) {
@@ -673,7 +685,6 @@ private void processOrderedStateChunkResponse(SnapSyncState state, Peer peer, Sn
673685 }
674686
675687 if (TrieDTOInOrderRecoverer .verifyChunk (state .getRemoteRootHash (), preRootNodes , nodes , postRootNodes )) {
676- state .getAllNodes ().addAll (nodes );
677688 state .setStateSize (state .getStateSize ().add (BigInteger .valueOf (trieElements .size ())));
678689 state .setStateChunkSize (state .getStateChunkSize ().add (BigInteger .valueOf (message .getChunkOfTrieKeyValue ().length )));
679690 if (message .isComplete ()) {
@@ -694,29 +705,48 @@ private boolean blocksVerified(SnapSyncState state) {
694705 return lastVerifiedBlockHeader != null && blockStore .isBlockExist (lastVerifiedBlockHeader .getParentHash ().getBytes ());
695706 }
696707
708+ private void moveNodesToTrie (TrieDTO node , int index ) {
709+ trieStore .saveDTO (node );
710+ }
711+
712+ TrieDTO getNodeFromTmpSnapSyncKeyValueDataSource (int index ) {
713+ final var nodeInBytes = tmpSnapSyncKeyValueDataSource .get (ByteUtil .intToBytes (index ));
714+ return TrieDTO .decodeFromSync (nodeInBytes );
715+ }
716+
697717 /**
698718 * Once state share is received, rebuild the trie, save it in db and save all the blocks.
699719 */
700720 private boolean rebuildStateAndSave (SnapSyncState state ) {
701721 logger .info ("Recovering trie..." );
702- final TrieDTO [] nodeArray = state .getAllNodes ().toArray (new TrieDTO [0 ]);
703- Optional <TrieDTO > result = TrieDTOInOrderRecoverer .recoverTrie (nodeArray , this .trieStore ::saveDTO );
722+ final var existingNodesSizeInBytes = tmpSnapSyncKeyValueDataSource .get (ByteUtil .intToBytes (TMP_NODES_SIZE_KEY ));
723+ final var existingNodesSize = ByteUtil .byteArrayToInt (existingNodesSizeInBytes );
724+ final var response = TrieDTOInOrderRecoverer .recoverTrie (this ::getNodeFromTmpSnapSyncKeyValueDataSource , existingNodesSize , this ::moveNodesToTrie );
725+ final var result = response .node ();
704726
705- if (result .isPresent () && Arrays .equals (state .getRemoteRootHash (), result .get ().calculateHash ())) {
706- logger .info ("State final validation OK! " );
727+ if (result .isEmpty () || ! Arrays .equals (state .getRemoteRootHash (), result .get ().calculateHash ())) {
728+ logger .error ("State final validation FAILED " );
707729
708- this . blockchain . removeBlocksByNumber ( 0 ) ;
709- //genesis is removed so backwards sync will always start.
730+ return false ;
731+ }
710732
711- BlockConnectorHelper blockConnector = new BlockConnectorHelper (this .blockStore );
712- state .connectBlocks (blockConnector );
713- logger .info ("Setting last block as best block..." );
714- this .blockchain .setStatus (state .getLastBlock (), state .getLastBlockDifficulty ());
715- this .transactionPool .setBestBlock (state .getLastBlock ());
716- return true ;
733+ for (int i = 0 ; i < existingNodesSize ; i ++) {
734+ tmpSnapSyncKeyValueDataSource .delete (ByteUtil .intToBytes (i ));
717735 }
718- logger .error ("State final validation FAILED" );
719- return false ;
736+
737+ tmpSnapSyncKeyValueDataSource .delete (ByteUtil .intToBytes (TMP_NODES_SIZE_KEY ));
738+
739+ logger .info ("State final validation OK!" );
740+
741+ this .blockchain .removeBlocksByNumber (0 );
742+ //genesis is removed so backwards sync will always start.
743+
744+ BlockConnectorHelper blockConnector = new BlockConnectorHelper (this .blockStore );
745+ state .connectBlocks (blockConnector );
746+ logger .info ("Setting last block as best block..." );
747+ this .blockchain .setStatus (state .getLastBlock (), state .getLastBlockDifficulty ());
748+ this .transactionPool .setBestBlock (state .getLastBlock ());
749+ return true ;
720750 }
721751
722752 private void generateChunkRequestTasks (SnapSyncState state ) {
0 commit comments