github.com/palcoin-project/palcd@v1.0.0/blockchain/validate_test.go (about) 1 // Copyright (c) 2013-2017 The btcsuite developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package blockchain 6 7 import ( 8 "math" 9 "reflect" 10 "testing" 11 "time" 12 13 "github.com/palcoin-project/palcd/chaincfg" 14 "github.com/palcoin-project/palcd/chaincfg/chainhash" 15 "github.com/palcoin-project/palcd/wire" 16 "github.com/palcoin-project/palcutil" 17 ) 18 19 // TestSequenceLocksActive tests the SequenceLockActive function to ensure it 20 // works as expected in all possible combinations/scenarios. 21 func TestSequenceLocksActive(t *testing.T) { 22 seqLock := func(h int32, s int64) *SequenceLock { 23 return &SequenceLock{ 24 Seconds: s, 25 BlockHeight: h, 26 } 27 } 28 29 tests := []struct { 30 seqLock *SequenceLock 31 blockHeight int32 32 mtp time.Time 33 34 want bool 35 }{ 36 // Block based sequence lock with equal block height. 37 {seqLock: seqLock(1000, -1), blockHeight: 1001, mtp: time.Unix(9, 0), want: true}, 38 39 // Time based sequence lock with mtp past the absolute time. 40 {seqLock: seqLock(-1, 30), blockHeight: 2, mtp: time.Unix(31, 0), want: true}, 41 42 // Block based sequence lock with current height below seq lock block height. 43 {seqLock: seqLock(1000, -1), blockHeight: 90, mtp: time.Unix(9, 0), want: false}, 44 45 // Time based sequence lock with current time before lock time. 46 {seqLock: seqLock(-1, 30), blockHeight: 2, mtp: time.Unix(29, 0), want: false}, 47 48 // Block based sequence lock at the same height, so shouldn't yet be active. 49 {seqLock: seqLock(1000, -1), blockHeight: 1000, mtp: time.Unix(9, 0), want: false}, 50 51 // Time based sequence lock with current time equal to lock time, so shouldn't yet be active. 52 {seqLock: seqLock(-1, 30), blockHeight: 2, mtp: time.Unix(30, 0), want: false}, 53 } 54 55 t.Logf("Running %d sequence locks tests", len(tests)) 56 for i, test := range tests { 57 got := SequenceLockActive(test.seqLock, 58 test.blockHeight, test.mtp) 59 if got != test.want { 60 t.Fatalf("SequenceLockActive #%d got %v want %v", i, 61 got, test.want) 62 } 63 } 64 } 65 66 // TestCheckConnectBlockTemplate tests the CheckConnectBlockTemplate function to 67 // ensure it fails. 68 func TestCheckConnectBlockTemplate(t *testing.T) { 69 // Create a new database and chain instance to run tests against. 70 chain, teardownFunc, err := chainSetup("checkconnectblocktemplate", 71 &chaincfg.MainNetParams) 72 if err != nil { 73 t.Errorf("Failed to setup chain instance: %v", err) 74 return 75 } 76 defer teardownFunc() 77 78 // Since we're not dealing with the real block chain, set the coinbase 79 // maturity to 1. 80 chain.TstSetCoinbaseMaturity(1) 81 82 // Load up blocks such that there is a side chain. 83 // (genesis block) -> 1 -> 2 -> 3 -> 4 84 // \-> 3a 85 testFiles := []string{ 86 "blk_0_to_4.dat.bz2", 87 "blk_3A.dat.bz2", 88 } 89 90 var blocks []*palcutil.Block 91 for _, file := range testFiles { 92 blockTmp, err := loadBlocks(file) 93 if err != nil { 94 t.Fatalf("Error loading file: %v\n", err) 95 } 96 blocks = append(blocks, blockTmp...) 97 } 98 99 for i := 1; i <= 3; i++ { 100 isMainChain, _, err := chain.ProcessBlock(blocks[i], BFNone) 101 if err != nil { 102 t.Fatalf("CheckConnectBlockTemplate: Received unexpected error "+ 103 "processing block %d: %v", i, err) 104 } 105 if !isMainChain { 106 t.Fatalf("CheckConnectBlockTemplate: Expected block %d to connect "+ 107 "to main chain", i) 108 } 109 } 110 111 // Block 3 should fail to connect since it's already inserted. 112 err = chain.CheckConnectBlockTemplate(blocks[3]) 113 if err == nil { 114 t.Fatal("CheckConnectBlockTemplate: Did not received expected error " + 115 "on block 3") 116 } 117 118 // Block 4 should connect successfully to tip of chain. 119 err = chain.CheckConnectBlockTemplate(blocks[4]) 120 if err != nil { 121 t.Fatalf("CheckConnectBlockTemplate: Received unexpected error on "+ 122 "block 4: %v", err) 123 } 124 125 // Block 3a should fail to connect since does not build on chain tip. 126 err = chain.CheckConnectBlockTemplate(blocks[5]) 127 if err == nil { 128 t.Fatal("CheckConnectBlockTemplate: Did not received expected error " + 129 "on block 3a") 130 } 131 132 // Block 4 should connect even if proof of work is invalid. 133 invalidPowBlock := *blocks[4].MsgBlock() 134 invalidPowBlock.Header.Nonce++ 135 err = chain.CheckConnectBlockTemplate(palcutil.NewBlock(&invalidPowBlock)) 136 if err != nil { 137 t.Fatalf("CheckConnectBlockTemplate: Received unexpected error on "+ 138 "block 4 with bad nonce: %v", err) 139 } 140 141 // Invalid block building on chain tip should fail to connect. 142 invalidBlock := *blocks[4].MsgBlock() 143 invalidBlock.Header.Bits-- 144 err = chain.CheckConnectBlockTemplate(palcutil.NewBlock(&invalidBlock)) 145 if err == nil { 146 t.Fatal("CheckConnectBlockTemplate: Did not received expected error " + 147 "on block 4 with invalid difficulty bits") 148 } 149 } 150 151 // TestCheckBlockSanity tests the CheckBlockSanity function to ensure it works 152 // as expected. 153 func TestCheckBlockSanity(t *testing.T) { 154 powLimit := chaincfg.MainNetParams.PowLimit 155 block := palcutil.NewBlock(&Block100000) 156 timeSource := NewMedianTime() 157 err := CheckBlockSanity(block, powLimit, timeSource) 158 if err != nil { 159 t.Errorf("CheckBlockSanity: %v", err) 160 } 161 162 // Ensure a block that has a timestamp with a precision higher than one 163 // second fails. 164 timestamp := block.MsgBlock().Header.Timestamp 165 block.MsgBlock().Header.Timestamp = timestamp.Add(time.Nanosecond) 166 err = CheckBlockSanity(block, powLimit, timeSource) 167 if err == nil { 168 t.Errorf("CheckBlockSanity: error is nil when it shouldn't be") 169 } 170 } 171 172 // TestCheckSerializedHeight tests the checkSerializedHeight function with 173 // various serialized heights and also does negative tests to ensure errors 174 // and handled properly. 175 func TestCheckSerializedHeight(t *testing.T) { 176 // Create an empty coinbase template to be used in the tests below. 177 coinbaseOutpoint := wire.NewOutPoint(&chainhash.Hash{}, math.MaxUint32) 178 coinbaseTx := wire.NewMsgTx(1) 179 coinbaseTx.AddTxIn(wire.NewTxIn(coinbaseOutpoint, nil, nil)) 180 181 // Expected rule errors. 182 missingHeightError := RuleError{ 183 ErrorCode: ErrMissingCoinbaseHeight, 184 } 185 badHeightError := RuleError{ 186 ErrorCode: ErrBadCoinbaseHeight, 187 } 188 189 tests := []struct { 190 sigScript []byte // Serialized data 191 wantHeight int32 // Expected height 192 err error // Expected error type 193 }{ 194 // No serialized height length. 195 {[]byte{}, 0, missingHeightError}, 196 // Serialized height length with no height bytes. 197 {[]byte{0x02}, 0, missingHeightError}, 198 // Serialized height length with too few height bytes. 199 {[]byte{0x02, 0x4a}, 0, missingHeightError}, 200 // Serialized height that needs 2 bytes to encode. 201 {[]byte{0x02, 0x4a, 0x52}, 21066, nil}, 202 // Serialized height that needs 2 bytes to encode, but backwards 203 // endianness. 204 {[]byte{0x02, 0x4a, 0x52}, 19026, badHeightError}, 205 // Serialized height that needs 3 bytes to encode. 206 {[]byte{0x03, 0x40, 0x0d, 0x03}, 200000, nil}, 207 // Serialized height that needs 3 bytes to encode, but backwards 208 // endianness. 209 {[]byte{0x03, 0x40, 0x0d, 0x03}, 1074594560, badHeightError}, 210 } 211 212 t.Logf("Running %d tests", len(tests)) 213 for i, test := range tests { 214 msgTx := coinbaseTx.Copy() 215 msgTx.TxIn[0].SignatureScript = test.sigScript 216 tx := palcutil.NewTx(msgTx) 217 218 err := checkSerializedHeight(tx, test.wantHeight) 219 if reflect.TypeOf(err) != reflect.TypeOf(test.err) { 220 t.Errorf("checkSerializedHeight #%d wrong error type "+ 221 "got: %v <%T>, want: %T", i, err, err, test.err) 222 continue 223 } 224 225 if rerr, ok := err.(RuleError); ok { 226 trerr := test.err.(RuleError) 227 if rerr.ErrorCode != trerr.ErrorCode { 228 t.Errorf("checkSerializedHeight #%d wrong "+ 229 "error code got: %v, want: %v", i, 230 rerr.ErrorCode, trerr.ErrorCode) 231 continue 232 } 233 } 234 } 235 } 236 237 // Block100000 defines block 100,000 of the block chain. It is used to 238 // test Block operations. 239 var Block100000 = wire.MsgBlock{ 240 Header: wire.BlockHeader{ 241 Version: 1, 242 PrevBlock: chainhash.Hash([32]byte{ // Make go vet happy. 243 0x50, 0x12, 0x01, 0x19, 0x17, 0x2a, 0x61, 0x04, 244 0x21, 0xa6, 0xc3, 0x01, 0x1d, 0xd3, 0x30, 0xd9, 245 0xdf, 0x07, 0xb6, 0x36, 0x16, 0xc2, 0xcc, 0x1f, 246 0x1c, 0xd0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 247 }), // 000000000002d01c1fccc21636b607dfd930d31d01c3a62104612a1719011250 248 MerkleRoot: chainhash.Hash([32]byte{ // Make go vet happy. 249 0x66, 0x57, 0xa9, 0x25, 0x2a, 0xac, 0xd5, 0xc0, 250 0xb2, 0x94, 0x09, 0x96, 0xec, 0xff, 0x95, 0x22, 251 0x28, 0xc3, 0x06, 0x7c, 0xc3, 0x8d, 0x48, 0x85, 252 0xef, 0xb5, 0xa4, 0xac, 0x42, 0x47, 0xe9, 0xf3, 253 }), // f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766 254 Timestamp: time.Unix(1293623863, 0), // 2010-12-29 11:57:43 +0000 UTC 255 Bits: 0x1b04864c, // 453281356 256 Nonce: 0x10572b0f, // 274148111 257 }, 258 Transactions: []*wire.MsgTx{ 259 { 260 Version: 1, 261 TxIn: []*wire.TxIn{ 262 { 263 PreviousOutPoint: wire.OutPoint{ 264 Hash: chainhash.Hash{}, 265 Index: 0xffffffff, 266 }, 267 SignatureScript: []byte{ 268 0x04, 0x4c, 0x86, 0x04, 0x1b, 0x02, 0x06, 0x02, 269 }, 270 Sequence: 0xffffffff, 271 }, 272 }, 273 TxOut: []*wire.TxOut{ 274 { 275 Value: 0x12a05f200, // 5000000000 276 PkScript: []byte{ 277 0x41, // OP_DATA_65 278 0x04, 0x1b, 0x0e, 0x8c, 0x25, 0x67, 0xc1, 0x25, 279 0x36, 0xaa, 0x13, 0x35, 0x7b, 0x79, 0xa0, 0x73, 280 0xdc, 0x44, 0x44, 0xac, 0xb8, 0x3c, 0x4e, 0xc7, 281 0xa0, 0xe2, 0xf9, 0x9d, 0xd7, 0x45, 0x75, 0x16, 282 0xc5, 0x81, 0x72, 0x42, 0xda, 0x79, 0x69, 0x24, 283 0xca, 0x4e, 0x99, 0x94, 0x7d, 0x08, 0x7f, 0xed, 284 0xf9, 0xce, 0x46, 0x7c, 0xb9, 0xf7, 0xc6, 0x28, 285 0x70, 0x78, 0xf8, 0x01, 0xdf, 0x27, 0x6f, 0xdf, 286 0x84, // 65-byte signature 287 0xac, // OP_CHECKSIG 288 }, 289 }, 290 }, 291 LockTime: 0, 292 }, 293 { 294 Version: 1, 295 TxIn: []*wire.TxIn{ 296 { 297 PreviousOutPoint: wire.OutPoint{ 298 Hash: chainhash.Hash([32]byte{ // Make go vet happy. 299 0x03, 0x2e, 0x38, 0xe9, 0xc0, 0xa8, 0x4c, 0x60, 300 0x46, 0xd6, 0x87, 0xd1, 0x05, 0x56, 0xdc, 0xac, 301 0xc4, 0x1d, 0x27, 0x5e, 0xc5, 0x5f, 0xc0, 0x07, 302 0x79, 0xac, 0x88, 0xfd, 0xf3, 0x57, 0xa1, 0x87, 303 }), // 87a157f3fd88ac7907c05fc55e271dc4acdc5605d187d646604ca8c0e9382e03 304 Index: 0, 305 }, 306 SignatureScript: []byte{ 307 0x49, // OP_DATA_73 308 0x30, 0x46, 0x02, 0x21, 0x00, 0xc3, 0x52, 0xd3, 309 0xdd, 0x99, 0x3a, 0x98, 0x1b, 0xeb, 0xa4, 0xa6, 310 0x3a, 0xd1, 0x5c, 0x20, 0x92, 0x75, 0xca, 0x94, 311 0x70, 0xab, 0xfc, 0xd5, 0x7d, 0xa9, 0x3b, 0x58, 312 0xe4, 0xeb, 0x5d, 0xce, 0x82, 0x02, 0x21, 0x00, 313 0x84, 0x07, 0x92, 0xbc, 0x1f, 0x45, 0x60, 0x62, 314 0x81, 0x9f, 0x15, 0xd3, 0x3e, 0xe7, 0x05, 0x5c, 315 0xf7, 0xb5, 0xee, 0x1a, 0xf1, 0xeb, 0xcc, 0x60, 316 0x28, 0xd9, 0xcd, 0xb1, 0xc3, 0xaf, 0x77, 0x48, 317 0x01, // 73-byte signature 318 0x41, // OP_DATA_65 319 0x04, 0xf4, 0x6d, 0xb5, 0xe9, 0xd6, 0x1a, 0x9d, 320 0xc2, 0x7b, 0x8d, 0x64, 0xad, 0x23, 0xe7, 0x38, 321 0x3a, 0x4e, 0x6c, 0xa1, 0x64, 0x59, 0x3c, 0x25, 322 0x27, 0xc0, 0x38, 0xc0, 0x85, 0x7e, 0xb6, 0x7e, 323 0xe8, 0xe8, 0x25, 0xdc, 0xa6, 0x50, 0x46, 0xb8, 324 0x2c, 0x93, 0x31, 0x58, 0x6c, 0x82, 0xe0, 0xfd, 325 0x1f, 0x63, 0x3f, 0x25, 0xf8, 0x7c, 0x16, 0x1b, 326 0xc6, 0xf8, 0xa6, 0x30, 0x12, 0x1d, 0xf2, 0xb3, 327 0xd3, // 65-byte pubkey 328 }, 329 Sequence: 0xffffffff, 330 }, 331 }, 332 TxOut: []*wire.TxOut{ 333 { 334 Value: 0x2123e300, // 556000000 335 PkScript: []byte{ 336 0x76, // OP_DUP 337 0xa9, // OP_HASH160 338 0x14, // OP_DATA_20 339 0xc3, 0x98, 0xef, 0xa9, 0xc3, 0x92, 0xba, 0x60, 340 0x13, 0xc5, 0xe0, 0x4e, 0xe7, 0x29, 0x75, 0x5e, 341 0xf7, 0xf5, 0x8b, 0x32, 342 0x88, // OP_EQUALVERIFY 343 0xac, // OP_CHECKSIG 344 }, 345 }, 346 { 347 Value: 0x108e20f00, // 4444000000 348 PkScript: []byte{ 349 0x76, // OP_DUP 350 0xa9, // OP_HASH160 351 0x14, // OP_DATA_20 352 0x94, 0x8c, 0x76, 0x5a, 0x69, 0x14, 0xd4, 0x3f, 353 0x2a, 0x7a, 0xc1, 0x77, 0xda, 0x2c, 0x2f, 0x6b, 354 0x52, 0xde, 0x3d, 0x7c, 355 0x88, // OP_EQUALVERIFY 356 0xac, // OP_CHECKSIG 357 }, 358 }, 359 }, 360 LockTime: 0, 361 }, 362 { 363 Version: 1, 364 TxIn: []*wire.TxIn{ 365 { 366 PreviousOutPoint: wire.OutPoint{ 367 Hash: chainhash.Hash([32]byte{ // Make go vet happy. 368 0xc3, 0x3e, 0xbf, 0xf2, 0xa7, 0x09, 0xf1, 0x3d, 369 0x9f, 0x9a, 0x75, 0x69, 0xab, 0x16, 0xa3, 0x27, 370 0x86, 0xaf, 0x7d, 0x7e, 0x2d, 0xe0, 0x92, 0x65, 371 0xe4, 0x1c, 0x61, 0xd0, 0x78, 0x29, 0x4e, 0xcf, 372 }), // cf4e2978d0611ce46592e02d7e7daf8627a316ab69759a9f3df109a7f2bf3ec3 373 Index: 1, 374 }, 375 SignatureScript: []byte{ 376 0x47, // OP_DATA_71 377 0x30, 0x44, 0x02, 0x20, 0x03, 0x2d, 0x30, 0xdf, 378 0x5e, 0xe6, 0xf5, 0x7f, 0xa4, 0x6c, 0xdd, 0xb5, 379 0xeb, 0x8d, 0x0d, 0x9f, 0xe8, 0xde, 0x6b, 0x34, 380 0x2d, 0x27, 0x94, 0x2a, 0xe9, 0x0a, 0x32, 0x31, 381 0xe0, 0xba, 0x33, 0x3e, 0x02, 0x20, 0x3d, 0xee, 382 0xe8, 0x06, 0x0f, 0xdc, 0x70, 0x23, 0x0a, 0x7f, 383 0x5b, 0x4a, 0xd7, 0xd7, 0xbc, 0x3e, 0x62, 0x8c, 384 0xbe, 0x21, 0x9a, 0x88, 0x6b, 0x84, 0x26, 0x9e, 385 0xae, 0xb8, 0x1e, 0x26, 0xb4, 0xfe, 0x01, 386 0x41, // OP_DATA_65 387 0x04, 0xae, 0x31, 0xc3, 0x1b, 0xf9, 0x12, 0x78, 388 0xd9, 0x9b, 0x83, 0x77, 0xa3, 0x5b, 0xbc, 0xe5, 389 0xb2, 0x7d, 0x9f, 0xff, 0x15, 0x45, 0x68, 0x39, 390 0xe9, 0x19, 0x45, 0x3f, 0xc7, 0xb3, 0xf7, 0x21, 391 0xf0, 0xba, 0x40, 0x3f, 0xf9, 0x6c, 0x9d, 0xee, 392 0xb6, 0x80, 0xe5, 0xfd, 0x34, 0x1c, 0x0f, 0xc3, 393 0xa7, 0xb9, 0x0d, 0xa4, 0x63, 0x1e, 0xe3, 0x95, 394 0x60, 0x63, 0x9d, 0xb4, 0x62, 0xe9, 0xcb, 0x85, 395 0x0f, // 65-byte pubkey 396 }, 397 Sequence: 0xffffffff, 398 }, 399 }, 400 TxOut: []*wire.TxOut{ 401 { 402 Value: 0xf4240, // 1000000 403 PkScript: []byte{ 404 0x76, // OP_DUP 405 0xa9, // OP_HASH160 406 0x14, // OP_DATA_20 407 0xb0, 0xdc, 0xbf, 0x97, 0xea, 0xbf, 0x44, 0x04, 408 0xe3, 0x1d, 0x95, 0x24, 0x77, 0xce, 0x82, 0x2d, 409 0xad, 0xbe, 0x7e, 0x10, 410 0x88, // OP_EQUALVERIFY 411 0xac, // OP_CHECKSIG 412 }, 413 }, 414 { 415 Value: 0x11d260c0, // 299000000 416 PkScript: []byte{ 417 0x76, // OP_DUP 418 0xa9, // OP_HASH160 419 0x14, // OP_DATA_20 420 0x6b, 0x12, 0x81, 0xee, 0xc2, 0x5a, 0xb4, 0xe1, 421 0xe0, 0x79, 0x3f, 0xf4, 0xe0, 0x8a, 0xb1, 0xab, 422 0xb3, 0x40, 0x9c, 0xd9, 423 0x88, // OP_EQUALVERIFY 424 0xac, // OP_CHECKSIG 425 }, 426 }, 427 }, 428 LockTime: 0, 429 }, 430 { 431 Version: 1, 432 TxIn: []*wire.TxIn{ 433 { 434 PreviousOutPoint: wire.OutPoint{ 435 Hash: chainhash.Hash([32]byte{ // Make go vet happy. 436 0x0b, 0x60, 0x72, 0xb3, 0x86, 0xd4, 0xa7, 0x73, 437 0x23, 0x52, 0x37, 0xf6, 0x4c, 0x11, 0x26, 0xac, 438 0x3b, 0x24, 0x0c, 0x84, 0xb9, 0x17, 0xa3, 0x90, 439 0x9b, 0xa1, 0xc4, 0x3d, 0xed, 0x5f, 0x51, 0xf4, 440 }), // f4515fed3dc4a19b90a317b9840c243bac26114cf637522373a7d486b372600b 441 Index: 0, 442 }, 443 SignatureScript: []byte{ 444 0x49, // OP_DATA_73 445 0x30, 0x46, 0x02, 0x21, 0x00, 0xbb, 0x1a, 0xd2, 446 0x6d, 0xf9, 0x30, 0xa5, 0x1c, 0xce, 0x11, 0x0c, 447 0xf4, 0x4f, 0x7a, 0x48, 0xc3, 0xc5, 0x61, 0xfd, 448 0x97, 0x75, 0x00, 0xb1, 0xae, 0x5d, 0x6b, 0x6f, 449 0xd1, 0x3d, 0x0b, 0x3f, 0x4a, 0x02, 0x21, 0x00, 450 0xc5, 0xb4, 0x29, 0x51, 0xac, 0xed, 0xff, 0x14, 451 0xab, 0xba, 0x27, 0x36, 0xfd, 0x57, 0x4b, 0xdb, 452 0x46, 0x5f, 0x3e, 0x6f, 0x8d, 0xa1, 0x2e, 0x2c, 453 0x53, 0x03, 0x95, 0x4a, 0xca, 0x7f, 0x78, 0xf3, 454 0x01, // 73-byte signature 455 0x41, // OP_DATA_65 456 0x04, 0xa7, 0x13, 0x5b, 0xfe, 0x82, 0x4c, 0x97, 457 0xec, 0xc0, 0x1e, 0xc7, 0xd7, 0xe3, 0x36, 0x18, 458 0x5c, 0x81, 0xe2, 0xaa, 0x2c, 0x41, 0xab, 0x17, 459 0x54, 0x07, 0xc0, 0x94, 0x84, 0xce, 0x96, 0x94, 460 0xb4, 0x49, 0x53, 0xfc, 0xb7, 0x51, 0x20, 0x65, 461 0x64, 0xa9, 0xc2, 0x4d, 0xd0, 0x94, 0xd4, 0x2f, 462 0xdb, 0xfd, 0xd5, 0xaa, 0xd3, 0xe0, 0x63, 0xce, 463 0x6a, 0xf4, 0xcf, 0xaa, 0xea, 0x4e, 0xa1, 0x4f, 464 0xbb, // 65-byte pubkey 465 }, 466 Sequence: 0xffffffff, 467 }, 468 }, 469 TxOut: []*wire.TxOut{ 470 { 471 Value: 0xf4240, // 1000000 472 PkScript: []byte{ 473 0x76, // OP_DUP 474 0xa9, // OP_HASH160 475 0x14, // OP_DATA_20 476 0x39, 0xaa, 0x3d, 0x56, 0x9e, 0x06, 0xa1, 0xd7, 477 0x92, 0x6d, 0xc4, 0xbe, 0x11, 0x93, 0xc9, 0x9b, 478 0xf2, 0xeb, 0x9e, 0xe0, 479 0x88, // OP_EQUALVERIFY 480 0xac, // OP_CHECKSIG 481 }, 482 }, 483 }, 484 LockTime: 0, 485 }, 486 }, 487 }