github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/test/utxo_view/utxo_view_test.go (about) 1 package utxo_view 2 3 import ( 4 "os" 5 "testing" 6 7 "github.com/bytom/bytom/testutil" 8 9 "github.com/golang/protobuf/proto" 10 11 "github.com/bytom/bytom/database" 12 "github.com/bytom/bytom/database/storage" 13 "github.com/bytom/bytom/protocol/bc" 14 "github.com/bytom/bytom/protocol/bc/types" 15 "github.com/bytom/bytom/protocol/state" 16 dbm "github.com/bytom/bytom/database/leveldb" 17 ) 18 19 func TestAttachOrDetachBlocks(t *testing.T) { 20 cases := []struct { 21 desc string 22 before map[bc.Hash]*storage.UtxoEntry 23 want map[bc.Hash]*storage.UtxoEntry 24 attachBlock []*bc.Block 25 detachBlock []*bc.Block 26 attachTxStatus []*bc.TransactionStatus 27 detachTxStatus []*bc.TransactionStatus 28 }{ 29 { 30 desc: "coinbase tx", 31 before: make(map[bc.Hash]*storage.UtxoEntry), 32 want: map[bc.Hash]*storage.UtxoEntry{*newTx(mockBlocks[0].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[0].Block.Height, false)}, 33 attachBlock: []*bc.Block{ 34 types.MapBlock(&mockBlocks[0].Block), 35 }, 36 attachTxStatus: []*bc.TransactionStatus{ 37 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 38 &bc.TxVerifyResult{StatusFail: false}, 39 }}, 40 }, 41 }, 42 { 43 desc: "Chain trading 3", 44 before: map[bc.Hash]*storage.UtxoEntry{ 45 newTx(mockBlocks[1].Transactions[1]).getSpentOutputID(0): storage.NewUtxoEntry(false, mockBlocks[1].Height-1, false), 46 }, 47 want: map[bc.Hash]*storage.UtxoEntry{ 48 *newTx(mockBlocks[1].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[1].Height, false), 49 *newTx(mockBlocks[1].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[1].Height, false), 50 *newTx(mockBlocks[1].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[1].Height, false), 51 *newTx(mockBlocks[1].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[1].Height, false), 52 *newTx(mockBlocks[1].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[1].Height, false), 53 }, 54 attachBlock: []*bc.Block{ 55 types.MapBlock(&mockBlocks[1].Block), 56 }, 57 attachTxStatus: []*bc.TransactionStatus{ 58 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 59 &bc.TxVerifyResult{StatusFail: false}, 60 &bc.TxVerifyResult{StatusFail: false}, 61 &bc.TxVerifyResult{StatusFail: false}, 62 &bc.TxVerifyResult{StatusFail: false}, 63 }}, 64 }, 65 }, 66 { 67 desc: "detach 1 block, attach 2 block", 68 before: map[bc.Hash]*storage.UtxoEntry{ 69 *newTx(mockBlocks[2].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[2].Height, false), 70 *newTx(mockBlocks[2].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[2].Height, false), 71 *newTx(mockBlocks[2].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[2].Height, false), 72 }, 73 want: map[bc.Hash]*storage.UtxoEntry{ 74 *newTx(mockBlocks[3].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[3].Height, false), 75 *newTx(mockBlocks[3].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[3].Height, false), 76 77 *newTx(mockBlocks[4].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[4].Height, false), 78 *newTx(mockBlocks[4].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[4].Height, false), 79 *newTx(mockBlocks[4].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[4].Height, false), 80 }, 81 attachBlock: []*bc.Block{ 82 types.MapBlock(&mockBlocks[3].Block), 83 types.MapBlock(&mockBlocks[4].Block), 84 }, 85 detachBlock: []*bc.Block{ 86 types.MapBlock(&mockBlocks[2].Block), 87 }, 88 attachTxStatus: []*bc.TransactionStatus{ 89 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 90 &bc.TxVerifyResult{StatusFail: false}, 91 &bc.TxVerifyResult{StatusFail: false}, 92 }}, 93 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 94 &bc.TxVerifyResult{StatusFail: false}, 95 &bc.TxVerifyResult{StatusFail: false}, 96 }}, 97 }, 98 detachTxStatus: []*bc.TransactionStatus{ 99 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 100 &bc.TxVerifyResult{StatusFail: false}, 101 &bc.TxVerifyResult{StatusFail: false}, 102 }}, 103 }, 104 }, 105 { 106 desc: "detach block 5, attach block 2", 107 before: map[bc.Hash]*storage.UtxoEntry{ 108 *newTx(mockBlocks[5].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[5].Height, false), 109 *newTx(mockBlocks[5].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[5].Height, false), 110 *newTx(mockBlocks[5].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[5].Height, false), 111 112 *newTx(mockBlocks[6].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[6].Height, false), 113 *newTx(mockBlocks[6].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[6].Height, false), 114 *newTx(mockBlocks[6].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[6].Height, false), 115 *newTx(mockBlocks[6].Transactions[1]).OutputHash(2): storage.NewUtxoEntry(false, mockBlocks[6].Height, false), 116 *newTx(mockBlocks[6].Transactions[1]).OutputHash(3): storage.NewUtxoEntry(false, mockBlocks[6].Height, false), 117 *newTx(mockBlocks[6].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[6].Height, false), 118 *newTx(mockBlocks[6].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[6].Height, false), 119 *newTx(mockBlocks[6].Transactions[2]).OutputHash(2): storage.NewUtxoEntry(false, mockBlocks[6].Height, false), 120 *newTx(mockBlocks[6].Transactions[2]).OutputHash(3): storage.NewUtxoEntry(false, mockBlocks[6].Height, false), 121 122 *newTx(mockBlocks[7].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[7].Height, false), 123 *newTx(mockBlocks[7].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[7].Height, false), 124 *newTx(mockBlocks[7].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[7].Height, false), 125 *newTx(mockBlocks[7].Transactions[1]).OutputHash(2): storage.NewUtxoEntry(false, mockBlocks[7].Height, false), 126 *newTx(mockBlocks[7].Transactions[1]).OutputHash(3): storage.NewUtxoEntry(false, mockBlocks[7].Height, false), 127 128 *newTx(mockBlocks[8].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[8].Height, false), 129 *newTx(mockBlocks[8].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[8].Height, false), 130 *newTx(mockBlocks[8].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[8].Height, false), 131 *newTx(mockBlocks[8].Transactions[1]).OutputHash(2): storage.NewUtxoEntry(false, mockBlocks[8].Height, false), 132 *newTx(mockBlocks[8].Transactions[1]).OutputHash(3): storage.NewUtxoEntry(false, mockBlocks[8].Height, false), 133 *newTx(mockBlocks[8].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[8].Height, false), 134 *newTx(mockBlocks[8].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[8].Height, false), 135 *newTx(mockBlocks[8].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[8].Height, false), 136 *newTx(mockBlocks[8].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[8].Height, false), 137 138 *newTx(mockBlocks[9].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[9].Height, false), 139 *newTx(mockBlocks[9].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[9].Height, false), 140 *newTx(mockBlocks[9].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[9].Height, false), 141 }, 142 want: map[bc.Hash]*storage.UtxoEntry{ 143 *newTx(mockBlocks[10].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[10].Height, false), 144 *newTx(mockBlocks[10].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 145 *newTx(mockBlocks[10].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 146 *newTx(mockBlocks[10].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 147 *newTx(mockBlocks[10].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 148 *newTx(mockBlocks[10].Transactions[2]).OutputHash(2): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 149 *newTx(mockBlocks[10].Transactions[2]).OutputHash(3): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 150 *newTx(mockBlocks[10].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 151 *newTx(mockBlocks[10].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 152 *newTx(mockBlocks[10].Transactions[3]).OutputHash(2): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 153 *newTx(mockBlocks[10].Transactions[3]).OutputHash(3): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 154 *newTx(mockBlocks[10].Transactions[4]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 155 *newTx(mockBlocks[10].Transactions[4]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 156 *newTx(mockBlocks[10].Transactions[4]).OutputHash(2): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 157 *newTx(mockBlocks[10].Transactions[4]).OutputHash(3): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 158 *newTx(mockBlocks[10].Transactions[5]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 159 *newTx(mockBlocks[10].Transactions[5]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 160 *newTx(mockBlocks[10].Transactions[5]).OutputHash(2): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 161 *newTx(mockBlocks[10].Transactions[5]).OutputHash(3): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 162 163 *newTx(mockBlocks[11].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[11].Height, false), 164 *newTx(mockBlocks[11].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[11].Height, false), 165 *newTx(mockBlocks[11].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[11].Height, false), 166 *newTx(mockBlocks[11].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[11].Height, false), 167 *newTx(mockBlocks[11].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[11].Height, false), 168 *newTx(mockBlocks[11].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[11].Height, false), 169 *newTx(mockBlocks[11].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[11].Height, false), 170 }, 171 attachBlock: []*bc.Block{ 172 types.MapBlock(&mockBlocks[10].Block), 173 types.MapBlock(&mockBlocks[11].Block), 174 }, 175 detachBlock: []*bc.Block{ 176 types.MapBlock(&mockBlocks[9].Block), 177 types.MapBlock(&mockBlocks[8].Block), 178 types.MapBlock(&mockBlocks[7].Block), 179 types.MapBlock(&mockBlocks[6].Block), 180 types.MapBlock(&mockBlocks[5].Block), 181 }, 182 attachTxStatus: []*bc.TransactionStatus{ 183 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 184 &bc.TxVerifyResult{StatusFail: false}, 185 &bc.TxVerifyResult{StatusFail: false}, 186 &bc.TxVerifyResult{StatusFail: false}, 187 &bc.TxVerifyResult{StatusFail: false}, 188 &bc.TxVerifyResult{StatusFail: false}, 189 &bc.TxVerifyResult{StatusFail: false}, 190 }}, 191 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 192 &bc.TxVerifyResult{StatusFail: false}, 193 &bc.TxVerifyResult{StatusFail: false}, 194 &bc.TxVerifyResult{StatusFail: false}, 195 &bc.TxVerifyResult{StatusFail: false}, 196 &bc.TxVerifyResult{StatusFail: false}, 197 }}, 198 }, 199 detachTxStatus: []*bc.TransactionStatus{ 200 201 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 202 &bc.TxVerifyResult{StatusFail: false}, 203 &bc.TxVerifyResult{StatusFail: false}, 204 }}, 205 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 206 &bc.TxVerifyResult{StatusFail: false}, 207 &bc.TxVerifyResult{StatusFail: false}, 208 &bc.TxVerifyResult{StatusFail: false}, 209 &bc.TxVerifyResult{StatusFail: false}, 210 }}, 211 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 212 &bc.TxVerifyResult{StatusFail: false}, 213 &bc.TxVerifyResult{StatusFail: false}, 214 }}, 215 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 216 &bc.TxVerifyResult{StatusFail: false}, 217 &bc.TxVerifyResult{StatusFail: false}, 218 &bc.TxVerifyResult{StatusFail: false}, 219 }}, 220 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 221 &bc.TxVerifyResult{StatusFail: false}, 222 &bc.TxVerifyResult{StatusFail: false}, 223 }}, 224 }, 225 }, 226 { 227 desc: "detach block 5, attach block 2. Other asset deals failed.", 228 before: map[bc.Hash]*storage.UtxoEntry{ 229 *newTx(mockBlocks[5].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[5].Height, false), 230 *newTx(mockBlocks[5].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[5].Height, false), 231 *newTx(mockBlocks[5].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[5].Height, false), 232 233 *newTx(mockBlocks[6].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[6].Height, false), 234 *newTx(mockBlocks[6].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[6].Height, false), 235 *newTx(mockBlocks[6].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[6].Height, false), 236 newTx(mockBlocks[6].Transactions[1]).getSpentOutputID(1): storage.NewUtxoEntry(false, mockBlocks[6].Height-1, false), 237 238 *newTx(mockBlocks[6].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[6].Height, false), 239 *newTx(mockBlocks[6].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[6].Height, false), 240 newTx(mockBlocks[6].Transactions[2]).getSpentOutputID(1): storage.NewUtxoEntry(false, mockBlocks[6].Height-1, false), 241 242 *newTx(mockBlocks[7].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[7].Height, false), 243 *newTx(mockBlocks[7].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[7].Height, false), 244 *newTx(mockBlocks[7].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[7].Height, false), 245 newTx(mockBlocks[7].Transactions[1]).getSpentOutputID(1): storage.NewUtxoEntry(false, mockBlocks[7].Height-1, false), 246 247 *newTx(mockBlocks[8].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[8].Height, false), 248 *newTx(mockBlocks[8].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[8].Height, false), 249 *newTx(mockBlocks[8].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[8].Height, false), 250 newTx(mockBlocks[8].Transactions[1]).getSpentOutputID(1): storage.NewUtxoEntry(false, mockBlocks[8].Height-1, false), 251 252 *newTx(mockBlocks[8].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[8].Height, false), 253 *newTx(mockBlocks[8].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[8].Height, false), 254 *newTx(mockBlocks[8].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[8].Height, false), 255 *newTx(mockBlocks[8].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[8].Height, false), 256 257 *newTx(mockBlocks[9].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[9].Height, false), 258 *newTx(mockBlocks[9].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[9].Height, false), 259 *newTx(mockBlocks[9].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[9].Height, false), 260 }, 261 want: map[bc.Hash]*storage.UtxoEntry{ 262 263 *newTx(mockBlocks[10].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[10].Height, false), 264 *newTx(mockBlocks[10].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 265 *newTx(mockBlocks[10].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 266 267 *newTx(mockBlocks[10].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 268 *newTx(mockBlocks[10].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 269 *newTx(mockBlocks[10].Transactions[2]).OutputHash(2): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 270 *newTx(mockBlocks[10].Transactions[2]).OutputHash(3): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 271 272 *newTx(mockBlocks[10].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 273 *newTx(mockBlocks[10].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 274 *newTx(mockBlocks[10].Transactions[3]).OutputHash(2): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 275 *newTx(mockBlocks[10].Transactions[3]).OutputHash(3): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 276 277 *newTx(mockBlocks[10].Transactions[4]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 278 *newTx(mockBlocks[10].Transactions[4]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 279 *newTx(mockBlocks[10].Transactions[4]).OutputHash(2): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 280 *newTx(mockBlocks[10].Transactions[4]).OutputHash(3): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 281 *newTx(mockBlocks[10].Transactions[5]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 282 *newTx(mockBlocks[10].Transactions[5]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 283 *newTx(mockBlocks[10].Transactions[5]).OutputHash(2): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 284 *newTx(mockBlocks[10].Transactions[5]).OutputHash(3): storage.NewUtxoEntry(false, mockBlocks[10].Height, false), 285 286 *newTx(mockBlocks[11].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[11].Height, false), 287 *newTx(mockBlocks[11].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[11].Height, false), 288 *newTx(mockBlocks[11].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[11].Height, false), 289 *newTx(mockBlocks[11].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[11].Height, false), 290 *newTx(mockBlocks[11].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[11].Height, false), 291 *newTx(mockBlocks[11].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[11].Height, false), 292 *newTx(mockBlocks[11].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[11].Height, false), 293 }, 294 attachBlock: []*bc.Block{ 295 types.MapBlock(&mockBlocks[10].Block), 296 types.MapBlock(&mockBlocks[11].Block), 297 }, 298 detachBlock: []*bc.Block{ 299 types.MapBlock(&mockBlocks[9].Block), 300 types.MapBlock(&mockBlocks[8].Block), 301 types.MapBlock(&mockBlocks[7].Block), 302 types.MapBlock(&mockBlocks[6].Block), 303 types.MapBlock(&mockBlocks[5].Block), 304 }, 305 attachTxStatus: []*bc.TransactionStatus{ 306 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 307 &bc.TxVerifyResult{StatusFail: false}, 308 &bc.TxVerifyResult{StatusFail: false}, 309 &bc.TxVerifyResult{StatusFail: false}, 310 &bc.TxVerifyResult{StatusFail: false}, 311 &bc.TxVerifyResult{StatusFail: false}, 312 &bc.TxVerifyResult{StatusFail: false}, 313 }}, 314 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 315 &bc.TxVerifyResult{StatusFail: false}, 316 &bc.TxVerifyResult{StatusFail: false}, 317 &bc.TxVerifyResult{StatusFail: false}, 318 &bc.TxVerifyResult{StatusFail: false}, 319 &bc.TxVerifyResult{StatusFail: false}, 320 }}, 321 }, 322 detachTxStatus: []*bc.TransactionStatus{ 323 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 324 &bc.TxVerifyResult{StatusFail: false}, 325 &bc.TxVerifyResult{StatusFail: false}, 326 }}, 327 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 328 &bc.TxVerifyResult{StatusFail: false}, 329 &bc.TxVerifyResult{StatusFail: true}, 330 &bc.TxVerifyResult{StatusFail: false}, 331 &bc.TxVerifyResult{StatusFail: false}, 332 }}, 333 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 334 &bc.TxVerifyResult{StatusFail: false}, 335 &bc.TxVerifyResult{StatusFail: true}, 336 }}, 337 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 338 &bc.TxVerifyResult{StatusFail: false}, 339 &bc.TxVerifyResult{StatusFail: true}, 340 &bc.TxVerifyResult{StatusFail: true}, 341 }}, 342 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 343 &bc.TxVerifyResult{StatusFail: false}, 344 &bc.TxVerifyResult{StatusFail: false}, 345 }}, 346 }, 347 }, 348 { 349 desc: "detach block 2, attach block 1. Chain trading", 350 before: map[bc.Hash]*storage.UtxoEntry{ 351 // coinbase tx 352 *newTx(mockBlocks[12].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[12].Height, false), 353 *newTx(mockBlocks[12].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[12].Height, false), 354 *newTx(mockBlocks[12].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[12].Height, false), 355 *newTx(mockBlocks[12].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[12].Height, false), 356 *newTx(mockBlocks[12].Transactions[4]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[12].Height, false), 357 358 *newTx(mockBlocks[13].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[13].Height, false), 359 *newTx(mockBlocks[13].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[13].Height, false), 360 *newTx(mockBlocks[13].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[13].Height, false), 361 *newTx(mockBlocks[13].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[13].Height, false), 362 }, 363 want: map[bc.Hash]*storage.UtxoEntry{ 364 newTx(mockBlocks[12].Transactions[1]).getSpentOutputID(0): storage.NewUtxoEntry(false, 0, false), 365 *newTx(mockBlocks[14].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[14].Height, false), 366 }, 367 attachBlock: []*bc.Block{ 368 types.MapBlock(&mockBlocks[14].Block), 369 }, 370 detachBlock: []*bc.Block{ 371 types.MapBlock(&mockBlocks[13].Block), 372 types.MapBlock(&mockBlocks[12].Block), 373 }, 374 attachTxStatus: []*bc.TransactionStatus{ 375 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 376 &bc.TxVerifyResult{StatusFail: false}, 377 &bc.TxVerifyResult{StatusFail: false}, 378 &bc.TxVerifyResult{StatusFail: false}, 379 &bc.TxVerifyResult{StatusFail: false}, 380 }}, 381 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 382 &bc.TxVerifyResult{StatusFail: false}, 383 &bc.TxVerifyResult{StatusFail: false}, 384 }}, 385 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 386 &bc.TxVerifyResult{StatusFail: false}, 387 &bc.TxVerifyResult{StatusFail: false}, 388 &bc.TxVerifyResult{StatusFail: false}, 389 }}, 390 }, 391 detachTxStatus: []*bc.TransactionStatus{ 392 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 393 &bc.TxVerifyResult{StatusFail: false}, 394 &bc.TxVerifyResult{StatusFail: false}, 395 &bc.TxVerifyResult{StatusFail: false}, 396 }}, 397 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{ 398 &bc.TxVerifyResult{StatusFail: false}, 399 &bc.TxVerifyResult{StatusFail: false}, 400 &bc.TxVerifyResult{StatusFail: false}, 401 &bc.TxVerifyResult{StatusFail: false}, 402 &bc.TxVerifyResult{StatusFail: false}, 403 }}, 404 }, 405 }, 406 } 407 node := blockNode(types.MapBlock(&mockBlocks[0].Block).BlockHeader) 408 defer os.RemoveAll("temp") 409 for index, c := range cases { 410 testDB := dbm.NewDB("testdb", "leveldb", "temp") 411 store := database.NewStore(testDB) 412 413 utxoViewpoint := state.NewUtxoViewpoint() 414 for k, v := range c.before { 415 utxoViewpoint.Entries[k] = v 416 } 417 if err := store.SaveChainStatus(node, utxoViewpoint); err != nil { 418 t.Error(err) 419 } 420 421 utxoViewpoint = state.NewUtxoViewpoint() 422 for index, block := range c.detachBlock { 423 if err := store.GetTransactionsUtxo(utxoViewpoint, block.Transactions); err != nil { 424 t.Error(err) 425 } 426 if err := utxoViewpoint.DetachBlock(block, c.detachTxStatus[index]); err != nil { 427 t.Error(err) 428 } 429 } 430 431 for index, block := range c.attachBlock { 432 if err := store.GetTransactionsUtxo(utxoViewpoint, block.Transactions); err != nil { 433 t.Error(err) 434 } 435 if err := utxoViewpoint.ApplyBlock(block, c.attachTxStatus[index]); err != nil { 436 t.Error(err) 437 } 438 } 439 if err := store.SaveChainStatus(node, utxoViewpoint); err != nil { 440 t.Error(err) 441 } 442 443 want := map[string]*storage.UtxoEntry{} 444 result := make(map[string]*storage.UtxoEntry) 445 446 for k, v := range c.want { 447 want[string(calcUtxoKey(&k))] = v 448 } 449 450 iter := testDB.IteratorPrefix([]byte(utxoPreFix)) 451 defer iter.Release() 452 453 for iter.Next() { 454 utxoEntry := &storage.UtxoEntry{} 455 if err := proto.Unmarshal(iter.Value(), utxoEntry); err != nil { 456 t.Error(err) 457 } 458 key := string(iter.Key()) 459 result[key] = utxoEntry 460 } 461 462 if !testutil.DeepEqual(want, result) { 463 t.Errorf("case [%d] fail. want: %v, result: %v", index, want, result) 464 } 465 testDB.Close() 466 os.RemoveAll("temp") 467 } 468 }