예제 #1
0
파일: opcode_test.go 프로젝트: decred/dcrd
// TestForVMFailure feeds random scripts to the VMs to check and see if it
// crashes. Try increasing the number of iterations or the length of the
// byte string to sample a greater space.
func TestForVMFailure(t *testing.T) {
	numTests := 2
	bsLength := 11

	for i := 0; i < numTests; i++ {
		tests := randByteSliceSlice(65536, bsLength, i)

		for j := range tests {
			if j == 0 {
				continue
			}

			msgTx := new(wire.MsgTx)
			msgTx.AddTxIn(&wire.TxIn{
				PreviousOutPoint: wire.OutPoint{},
				SignatureScript:  tests[j-1],
				Sequence:         0xFFFFFFFF,
			})
			msgTx.AddTxOut(&wire.TxOut{
				Value:    0x00FFFFFF00000000,
				PkScript: []byte{0x01},
			})
			flags := StandardVerifyFlags
			engine, err := NewEngine(tests[j], msgTx, 0, flags, 0,
				nil)

			if err == nil {
				engine.Execute()
			}
		}
	}
}
예제 #2
0
파일: tx.go 프로젝트: decred/dcrutil
// NewTxDeepTxIns is used to deep copy a transaction, maintaining the old
// pointers to the TxOuts while replacing the old pointers to the TxIns with
// deep copies. This is to prevent races when the fraud proofs for the
// transactions are set by the miner.
func NewTxDeepTxIns(msgTx *wire.MsgTx) *Tx {
	if msgTx == nil {
		return nil
	}

	newMsgTx := new(wire.MsgTx)

	// Copy the fixed fields.
	newMsgTx.Version = msgTx.Version
	newMsgTx.LockTime = msgTx.LockTime
	newMsgTx.Expiry = msgTx.Expiry

	// Copy the TxIns deeply.
	for _, txIn := range msgTx.TxIn {
		sigScrLen := len(txIn.SignatureScript)
		sigScrCopy := make([]byte, sigScrLen, sigScrLen)

		txInCopy := new(wire.TxIn)
		txInCopy.PreviousOutPoint.Hash = txIn.PreviousOutPoint.Hash
		txInCopy.PreviousOutPoint.Index = txIn.PreviousOutPoint.Index
		txInCopy.PreviousOutPoint.Tree = txIn.PreviousOutPoint.Tree

		txInCopy.Sequence = txIn.Sequence
		txInCopy.ValueIn = txIn.ValueIn
		txInCopy.BlockHeight = txIn.BlockHeight
		txInCopy.BlockIndex = txIn.BlockIndex

		txInCopy.SignatureScript = sigScrCopy

		newMsgTx.AddTxIn(txIn)
	}

	// Shallow copy the TxOuts.
	for _, txOut := range msgTx.TxOut {
		newMsgTx.AddTxOut(txOut)
	}

	return &Tx{
		hash:    msgTx.TxHash(),
		msgTx:   msgTx,
		txTree:  wire.TxTreeUnknown,
		txIndex: TxIndexUnknown,
	}
}
예제 #3
0
파일: dup_test.go 프로젝트: ironbits/dcrd
func Test_dupTx(t *testing.T) {

	// Ignore db remove errors since it means we didn't have an old one.
	dbname := fmt.Sprintf("tstdbdup0")
	dbnamever := dbname + ".ver"
	_ = os.RemoveAll(dbname)
	_ = os.RemoveAll(dbnamever)
	db, err := database.CreateDB("leveldb", dbname)
	if err != nil {
		t.Errorf("Failed to open test database %v", err)
		return
	}
	defer os.RemoveAll(dbname)
	defer os.RemoveAll(dbnamever)
	defer func() {
		if err := db.Close(); err != nil {
			t.Errorf("Close: unexpected error: %v", err)
		}
	}()

	testdatafile := filepath.Join("../", "../blockchain/testdata", "blocks0to168.bz2")
	blocks, err := loadBlocks(t, testdatafile)
	if err != nil {
		t.Errorf("Unable to load blocks from test data for: %v",
			err)
		return
	}

	var lastSha *chainhash.Hash

	// Populate with the fisrt 256 blocks, so we have blocks to 'mess with'
	err = nil
out:
	for height := int64(0); height < int64(len(blocks)); height++ {
		block := blocks[height]
		if height != 0 {
			// except for NoVerify which does not allow lookups check inputs
			mblock := block.MsgBlock()
			//t.Errorf("%v", blockchain.DebugBlockString(block))
			parentBlock := blocks[height-1]
			mParentBlock := parentBlock.MsgBlock()
			var txneededList []*chainhash.Hash
			opSpentInBlock := make(map[wire.OutPoint]struct{})
			if dcrutil.IsFlagSet16(dcrutil.BlockValid, mParentBlock.Header.VoteBits) {
				for _, tx := range mParentBlock.Transactions {
					for _, txin := range tx.TxIn {
						if txin.PreviousOutPoint.Index == uint32(4294967295) {
							continue
						}

						if existsInOwnBlockRegTree(mParentBlock, txin.PreviousOutPoint.Hash) {
							_, used := opSpentInBlock[txin.PreviousOutPoint]
							if !used {
								// Origin tx is in the block and so hasn't been
								// added yet, continue
								opSpentInBlock[txin.PreviousOutPoint] = struct{}{}
								continue
							} else {
								t.Errorf("output ref %v attempted double spend of previously spend output", txin.PreviousOutPoint)
							}
						}

						origintxsha := &txin.PreviousOutPoint.Hash
						txneededList = append(txneededList, origintxsha)
						exists, err := db.ExistsTxSha(origintxsha)
						if err != nil {
							t.Errorf("ExistsTxSha: unexpected error %v ", err)
						}
						if !exists {
							t.Errorf("referenced tx not found %v (height %v)", origintxsha, height)
						}

						_, err = db.FetchTxBySha(origintxsha)
						if err != nil {
							t.Errorf("referenced tx not found %v err %v ", origintxsha, err)
						}
					}
				}
			}
			for _, stx := range mblock.STransactions {
				for _, txin := range stx.TxIn {
					if txin.PreviousOutPoint.Index == uint32(4294967295) {
						continue
					}
					if existsInOwnBlockRegTree(mParentBlock, txin.PreviousOutPoint.Hash) {
						_, used := opSpentInBlock[txin.PreviousOutPoint]
						if !used {
							// Origin tx is in the block and so hasn't been
							// added yet, continue
							opSpentInBlock[txin.PreviousOutPoint] = struct{}{}
							continue
						} else {
							t.Errorf("output ref %v attempted double spend of previously spend output", txin.PreviousOutPoint)
						}
					}

					origintxsha := &txin.PreviousOutPoint.Hash
					txneededList = append(txneededList, origintxsha)

					exists, err := db.ExistsTxSha(origintxsha)
					if err != nil {
						t.Errorf("ExistsTxSha: unexpected error %v ", err)
					}
					if !exists {
						t.Errorf("referenced tx not found %v", origintxsha)
					}

					_, err = db.FetchTxBySha(origintxsha)
					if err != nil {
						t.Errorf("referenced tx not found %v err %v ", origintxsha, err)
					}
				}
			}
			txlist := db.FetchUnSpentTxByShaList(txneededList)
			for _, txe := range txlist {
				if txe.Err != nil {
					t.Errorf("tx list fetch failed %v err %v ", txe.Sha, txe.Err)
					break out
				}
			}
		}
		newheight, err := db.InsertBlock(block)
		if err != nil {
			t.Errorf("failed to insert block %v err %v", height, err)
			break out
		}
		if newheight != height {
			t.Errorf("height mismatch expect %v returned %v", height, newheight)
			break out
		}

		newSha, blkid, err := db.NewestSha()
		if err != nil {
			t.Errorf("failed to obtain latest sha %v %v", height, err)
		}

		if blkid != height {
			t.Errorf("height doe not match latest block height %v %v %v", blkid, height, err)
		}

		blkSha := block.Sha()
		if *newSha != *blkSha {
			t.Errorf("Newest block sha does not match freshly inserted one %v %v %v ", newSha, blkSha, err)
		}
		lastSha = blkSha
	}

	// generate a new block based on the last sha
	// these block are not verified, so there are a bunch of garbage fields
	// in the 'generated' block.

	var bh wire.BlockHeader

	bh.Version = 0
	bh.PrevBlock = *lastSha
	// Bits, Nonce are not filled in

	mblk := wire.NewMsgBlock(&bh)

	hash, _ := chainhash.NewHashFromStr("c23953c56cb2ef8e4698e3ed3b0fc4c837754d3cd16485192d893e35f32626b4")

	po := wire.NewOutPoint(hash, 0, dcrutil.TxTreeRegular)
	txI := wire.NewTxIn(po, []byte("garbage"))
	txO := wire.NewTxOut(50000000, []byte("garbageout"))

	var tx wire.MsgTx
	tx.AddTxIn(txI)
	tx.AddTxOut(txO)

	mblk.AddTransaction(&tx)

	blk := dcrutil.NewBlock(mblk)

	fetchList := []*chainhash.Hash{hash}
	listReply := db.FetchUnSpentTxByShaList(fetchList)
	for _, lr := range listReply {
		if lr.Err != nil {
			t.Errorf("sha %v spent %v err %v\n", lr.Sha,
				lr.TxSpent, lr.Err)
		}
	}

	_, err = db.InsertBlock(blk)
	if err != nil {
		t.Errorf("failed to insert phony block %v", err)
	}

	// ok, did it 'spend' the tx ?

	listReply = db.FetchUnSpentTxByShaList(fetchList)
	for _, lr := range listReply {
		if lr.Err != nil && lr.Err != database.ErrTxShaMissing {
			t.Errorf("sha %v spent %v err %v\n", lr.Sha,
				lr.TxSpent, lr.Err)
		}
	}

	txlist := blk.Transactions()
	for _, tx := range txlist {
		txsha := tx.Sha()
		txReply, err := db.FetchTxBySha(txsha)
		if err != nil {
			t.Errorf("fully spent lookup %v err %v\n", hash, err)
		} else {
			for _, lr := range txReply {
				if lr.Err != nil {
					t.Errorf("stx %v spent %v err %v\n", lr.Sha,
						lr.TxSpent, lr.Err)
				}
			}
		}
	}

	err = db.DropAfterBlockBySha(lastSha)
	if err != nil {
		t.Errorf("failed to drop spending block %v", err)
	}
}
예제 #4
0
파일: opcode_test.go 프로젝트: decred/dcrd
func TestNewlyEnabledOpCodes(t *testing.T) {
	sigScriptMath := []byte{
		0x04,
		0xff, 0xff, 0xff, 0x7f,
		0x04,
		0xee, 0xee, 0xee, 0x6e,
	}
	sigScriptShift := []byte{
		0x04,
		0xff, 0xff, 0xff, 0x7f,
		0x53,
	}
	sigScriptRot := []byte{
		0x04,
		0x21, 0x12, 0x34, 0x56,
		0x53,
	}
	sigScriptInv := []byte{
		0x04,
		0xff, 0x00, 0xf0, 0x0f,
	}
	sigScriptLogic := []byte{
		0x04,
		0x21, 0x12, 0x34, 0x56,
		0x04,
		0x0f, 0xf0, 0x00, 0xff,
	}
	sigScriptCat := []byte{
		0x06,
		0x21, 0x12, 0x34, 0x56, 0x44, 0x55,
		0x06,
		0x0f, 0xf0, 0x00, 0xff, 0x88, 0x99,
	}
	lotsOf01s := bytes.Repeat([]byte{0x01}, 2050)
	builder := NewScriptBuilder()
	builder.AddData(lotsOf01s).AddData(lotsOf01s)
	sigScriptCatOverflow, _ := builder.Script()
	sigScriptSubstr := []byte{
		0x08,
		0x21, 0x12, 0x34, 0x56, 0x59, 0x32, 0x40, 0x21,
		0x56,
		0x52,
	}
	sigScriptLR := []byte{
		0x08,
		0x21, 0x12, 0x34, 0x56, 0x59, 0x32, 0x40, 0x21,
		0x54,
	}

	tests := []struct {
		name      string
		pkScript  []byte
		sigScript []byte
		expected  bool
	}{
		{
			name: "add",
			pkScript: []byte{
				0x93, // OP_ADD
				0x05, // Expected result push
				0xed, 0xee, 0xee, 0xee, 0x00,
				0x87, // OP_EQUAL
			},
			sigScript: sigScriptMath,
			expected:  true,
		},
		{
			name: "sub",
			pkScript: []byte{
				0x94, // OP_SUB
				0x04, // Expected result push
				0x11, 0x11, 0x11, 0x11,
				0x87, // OP_EQUAL
			},
			sigScript: sigScriptMath,
			expected:  true,
		},
		{
			name: "mul",
			pkScript: []byte{
				0x95, // OP_MUL
				0x04, // Expected result push
				0xee, 0xee, 0xee, 0xee,
				0x87, // OP_EQUAL
			},
			sigScript: sigScriptMath,
			expected:  true,
		},
		{
			name: "div",
			pkScript: []byte{
				0x96, // OP_DIV
				0x51, // Expected result push
				0x87, // OP_EQUAL
			},
			sigScript: sigScriptMath,
			expected:  true,
		},
		{
			name: "mod",
			pkScript: []byte{
				0x97, // OP_MOD
				0x04, // Expected result push
				0x11, 0x11, 0x11, 0x11,
				0x87, // OP_EQUAL
			},
			sigScript: sigScriptMath,
			expected:  true,
		},
		{
			name: "lshift",
			pkScript: []byte{
				0x98, // OP_LSHIFT
				0x01, // Expected result push
				0x88,
				0x87, // OP_EQUAL
			},
			sigScript: sigScriptShift,
			expected:  true,
		},
		{
			name: "rshift",
			pkScript: []byte{
				0x99, // OP_RSHIFT
				0x04, // Expected result push
				0xff, 0xff, 0xff, 0x0f,
				0x87, // OP_EQUAL
			},
			sigScript: sigScriptShift,
			expected:  true,
		},
		{
			name: "rotr",
			pkScript: []byte{
				0x89, // OP_ROTR
				0x04, // Expected result push
				0x44, 0x82, 0xc6, 0x2a,
				0x87, // OP_EQUAL
			},
			sigScript: sigScriptRot,
			expected:  true,
		},
		{
			name: "rotl",
			pkScript: []byte{
				0x8a, // OP_ROTL
				0x04, // Expected result push
				0xf6, 0x6e, 0x5f, 0xce,
				0x87, // OP_EQUAL
			},
			sigScript: sigScriptRot,
			expected:  true,
		},
		{
			name: "inv",
			pkScript: []byte{
				0x83, // OP_INV
				0x04, // Expected result push
				0x00, 0x01, 0xf0, 0x8f,
				0x87, // OP_EQUAL
			},
			sigScript: sigScriptInv,
			expected:  true,
		},
		{
			name: "and",
			pkScript: []byte{
				0x84, // OP_AND
				0x03, // Expected result push
				0x21, 0x02, 0x34,
				0x87, // OP_EQUAL
			},
			sigScript: sigScriptLogic,
			expected:  true,
		},
		{
			name: "or",
			pkScript: []byte{
				0x85, // OP_OR
				0x04, // Expected result push
				0x0f, 0xe0, 0x00, 0xa9,
				0x87, // OP_EQUAL
			},
			sigScript: sigScriptLogic,
			expected:  true,
		},
		{
			name: "xor",
			pkScript: []byte{
				0x86, // OP_XOR
				0x04, // Expected result push
				0x30, 0xe2, 0x34, 0xa9,
				0x87, // OP_EQUAL
			},
			sigScript: sigScriptLogic,
			expected:  true,
		},
		{
			name: "cat",
			pkScript: []byte{
				0x7e, // OP_CAT
				0x0c, // Expected result push
				0x21, 0x12, 0x34, 0x56, 0x44, 0x55,
				0x0f, 0xf0, 0x00, 0xff, 0x88, 0x99,
				0x87, // OP_EQUAL
			},
			sigScript: sigScriptCat,
			expected:  true,
		},
		{
			name: "catoverflow",
			pkScript: []byte{
				0x7e, // OP_CAT
				0x0c, // Expected result push
				0x21, 0x12, 0x34, 0x56, 0x44, 0x55,
				0x0f, 0xf0, 0x00, 0xff, 0x88, 0x99,
				0x87, // OP_EQUAL
			},
			sigScript: sigScriptCatOverflow,
			expected:  false,
		},
		{
			name: "substr",
			pkScript: []byte{
				0x7f, // OP_SUBSTR
				0x04, // Expected result push
				0x34, 0x56, 0x59, 0x32,
				0x87, // OP_EQUAL
			},
			sigScript: sigScriptSubstr,
			expected:  true,
		},
		{
			name: "left",
			pkScript: []byte{
				0x80, // OP_LEFT
				0x04, // Expected result push
				0x21, 0x12, 0x34, 0x56,
				0x87, // OP_EQUAL
			},
			sigScript: sigScriptLR,
			expected:  true,
		},
		{
			name: "right",
			pkScript: []byte{
				0x81, // OP_RIGHT
				0x04, // Expected result push
				0x59, 0x32, 0x40, 0x21,
				0x87, // OP_EQUAL
			},
			sigScript: sigScriptLR,
			expected:  true,
		},
	}

	for _, test := range tests {
		msgTx := new(wire.MsgTx)
		msgTx.AddTxIn(&wire.TxIn{
			PreviousOutPoint: wire.OutPoint{},
			SignatureScript:  test.sigScript,
			Sequence:         0xFFFFFFFF,
		})
		msgTx.AddTxOut(&wire.TxOut{
			Value:    0x00FFFFFF00000000,
			PkScript: []byte{0x01},
		})
		flags := StandardVerifyFlags
		engine, err := NewEngine(test.pkScript, msgTx, 0, flags, 0, nil)
		if err != nil {
			t.Errorf("Bad script result for test %v because of error: %v",
				test.name, err.Error())
			continue
		}
		err = engine.Execute()
		if err != nil && test.expected {
			t.Errorf("Bad script exec for test %v because of error: %v",
				test.name, err.Error())
		}
	}
}
예제 #5
0
// TestCalcSignatureHash does some rudimentary testing of msg hash calculation.
func TestCalcSignatureHash(t *testing.T) {
	tx := new(wire.MsgTx)
	for i := 0; i < 3; i++ {
		txIn := new(wire.TxIn)
		txIn.Sequence = 0xFFFFFFFF
		txIn.PreviousOutPoint.Hash = chainhash.HashFuncH([]byte{byte(i)})
		txIn.PreviousOutPoint.Index = uint32(i)
		txIn.PreviousOutPoint.Tree = int8(0)
		tx.AddTxIn(txIn)
	}
	for i := 0; i < 2; i++ {
		txOut := new(wire.TxOut)
		txOut.PkScript = []byte{0x01, 0x01, 0x02, 0x03}
		txOut.Value = 0x0000FF00FF00FF00
		tx.AddTxOut(txOut)
	}

	want, _ := hex.DecodeString("d09285b6f60c71329323bc2e76c48" +
		"a462cde4e1032aa8f59c55823f1722c7f4a")
	pops, _ := txscript.TstParseScript([]byte{0x01, 0x01, 0x02, 0x03})

	// Test prefix caching.
	msg1, err := txscript.CalcSignatureHash(pops, txscript.SigHashAll, tx, 0, nil)
	if err != nil {
		t.Fatalf("unexpected error %v", err.Error())
	}

	prefixHash := tx.TxSha()
	msg2, err := txscript.CalcSignatureHash(pops, txscript.SigHashAll, tx, 0,
		&prefixHash)
	if err != nil {
		t.Fatalf("unexpected error %v", err.Error())
	}

	if !bytes.Equal(msg1, want) {
		t.Errorf("for sighash all sig noncached wrong msg %x given, want %x",
			msg1,
			want)
	}
	if !bytes.Equal(msg2, want) {
		t.Errorf("for sighash all sig cached wrong msg %x given, want %x",
			msg1,
			want)
	}
	if !bytes.Equal(msg1, msg2) {
		t.Errorf("for sighash all sig non-equivalent msgs %x and %x were "+
			"returned when using a cached prefix",
			msg1,
			msg2)
	}

	// Move the index and make sure that we get a whole new hash, despite
	// using the same TxOuts.
	msg3, err := txscript.CalcSignatureHash(pops, txscript.SigHashAll, tx, 1,
		&prefixHash)
	if err != nil {
		t.Fatalf("unexpected error %v", err.Error())
	}

	if bytes.Equal(msg1, msg3) {
		t.Errorf("for sighash all sig equivalent msgs %x and %x were "+
			"returned when using a cached prefix but different indices",
			msg1,
			msg3)
	}
}