@@ -28,7 +28,6 @@ func TestKVLedgerBlockStorage(t *testing.T) {
28
28
defer env.cleanup()
29
29
ledger, _ := NewKVLedger(env.conf)
30
30
defer ledger.Close()
31
-
32
31
bcInfo, _ := ledger.GetBlockchainInfo()
33
32
testutil.AssertEquals(t, bcInfo, &pb.BlockchainInfo{
34
33
Height: 0, CurrentBlockHash: nil, PreviousBlockHash: nil})
@@ -76,3 +75,85 @@ func TestKVLedgerBlockStorage(t *testing.T) {
76
75
b2, _ = ledger.GetBlockByNumber(2)
77
76
testutil.AssertEquals(t, b2, block2)
78
77
}
78
+
79
+ func TestKVLedgerStateDBRecovery(t *testing.T) {
80
+ env := newTestEnv(t)
81
+ defer env.cleanup()
82
+ ledger, _ := NewKVLedger(env.conf)
83
+ defer ledger.Close()
84
+
85
+ bcInfo, _ := ledger.GetBlockchainInfo()
86
+ testutil.AssertEquals(t, bcInfo, &pb.BlockchainInfo{
87
+ Height: 0, CurrentBlockHash: nil, PreviousBlockHash: nil})
88
+
89
+ //creating and committing the first block
90
+ simulator, _ := ledger.NewTxSimulator()
91
+ //simulating a transaction
92
+ simulator.SetState("ns1", "key1", []byte("value1"))
93
+ simulator.SetState("ns1", "key2", []byte("value2"))
94
+ simulator.SetState("ns1", "key3", []byte("value3"))
95
+ simulator.Done()
96
+ simRes, _ := simulator.GetTxSimulationResults()
97
+ //generating a block based on the simulation result
98
+ bg := testutil.NewBlockGenerator(t)
99
+ block1 := bg.NextBlock([][]byte{simRes}, false)
100
+ //performing validation of read and write set to find valid transactions
101
+ ledger.RemoveInvalidTransactionsAndPrepare(block1)
102
+ //writing the validated block to block storage and committing the transaction to state DB
103
+ ledger.Commit()
104
+
105
+ bcInfo, _ = ledger.GetBlockchainInfo()
106
+ block1Hash := block1.Header.Hash()
107
+ testutil.AssertEquals(t, bcInfo, &pb.BlockchainInfo{
108
+ Height: 1, CurrentBlockHash: block1Hash, PreviousBlockHash: []byte{}})
109
+
110
+ //creating the second block but peer fails before committing the transaction to state DB
111
+ simulator, _ = ledger.NewTxSimulator()
112
+ //simulating transaction
113
+ simulator.SetState("ns1", "key1", []byte("value4"))
114
+ simulator.SetState("ns1", "key2", []byte("value5"))
115
+ simulator.SetState("ns1", "key3", []byte("value6"))
116
+ simulator.Done()
117
+ simRes, _ = simulator.GetTxSimulationResults()
118
+ //generating a block based on the simulation result
119
+ block2 := bg.NextBlock([][]byte{simRes}, false)
120
+ //performing validation of read and write set to find valid transactions
121
+ ledger.RemoveInvalidTransactionsAndPrepare(block2)
122
+ //writing the validated block to block storage but not committing the transaction to state DB
123
+ ledger.blockStore.AddBlock(ledger.pendingBlockToCommit)
124
+ //assume that peer fails here before committing the transaction
125
+
126
+ bcInfo, _ = ledger.GetBlockchainInfo()
127
+ block2Hash := block2.Header.Hash()
128
+ testutil.AssertEquals(t, bcInfo, &pb.BlockchainInfo{
129
+ Height: 2, CurrentBlockHash: block2Hash, PreviousBlockHash: block1.Header.Hash()})
130
+
131
+ simulator, _ = ledger.NewTxSimulator()
132
+ value, _ := simulator.GetState("ns1", "key1")
133
+ //value for 'key1' should be 'value1' as the last commit failed
134
+ testutil.AssertEquals(t, value, []byte("value1"))
135
+ value, _ = simulator.GetState("ns1", "key2")
136
+ //value for 'key2' should be 'value2' as the last commit failed
137
+ testutil.AssertEquals(t, value, []byte("value2"))
138
+ value, _ = simulator.GetState("ns1", "key3")
139
+ //value for 'key3' should be 'value3' as the last commit failed
140
+ testutil.AssertEquals(t, value, []byte("value3"))
141
+ simulator.Done()
142
+ ledger.Close()
143
+
144
+ //we assume here that the peer comes online and calls NewKVLedger to get a handler for the ledger
145
+ //State DB should be recovered before returning from NewKVLedger call
146
+ ledger, _ = NewKVLedger(env.conf)
147
+ simulator, _ = ledger.NewTxSimulator()
148
+ value, _ = simulator.GetState("ns1", "key1")
149
+ //value for 'key1' should be 'value4' after recovery
150
+ testutil.AssertEquals(t, value, []byte("value4"))
151
+ value, _ = simulator.GetState("ns1", "key2")
152
+ //value for 'key2' should be 'value5' after recovery
153
+ testutil.AssertEquals(t, value, []byte("value5"))
154
+ value, _ = simulator.GetState("ns1", "key3")
155
+ //value for 'key3' should be 'value6' after recovery
156
+ testutil.AssertEquals(t, value, []byte("value6"))
157
+ simulator.Done()
158
+ ledger.Close()
159
+ }
0 commit comments