// SignRawTransaction2Async returns an instance of a type that can be used to
// get the result of the RPC at some future time by invoking the Receive
// function on the returned instance.
//
// See SignRawTransaction2 for the blocking version and more details.
func (c *Client) SignRawTransaction2Async(tx *wire.MsgTx, inputs []dcrjson.RawTxInput) FutureSignRawTransactionResult {
	txHex := ""
	if tx != nil {
		// Serialize the transaction and convert to hex string.
		buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
		if err := tx.Serialize(buf); err != nil {
			return newFutureError(err)
		}
		txHex = hex.EncodeToString(buf.Bytes())
	}

	cmd := dcrjson.NewSignRawTransactionCmd(txHex, &inputs, nil, nil)
	return c.sendCmd(cmd)
}
Example #2
0
// dbFetchTx looks up the passed transaction hash in the transaction index and
// loads it from the database.
func dbFetchTx(dbTx database.Tx, hash chainhash.Hash) (*wire.MsgTx, error) {
	// Look up the location of the transaction.
	blockRegion, err := dbFetchTxIndexEntry(dbTx, hash)
	if err != nil {
		return nil, err
	}
	if blockRegion == nil {
		return nil, fmt.Errorf("transaction %v not found in the txindex", hash)
	}

	// Load the raw transaction bytes from the database.
	txBytes, err := dbTx.FetchBlockRegion(blockRegion)
	if err != nil {
		return nil, err
	}

	// Deserialize the transaction.
	var msgTx wire.MsgTx
	err = msgTx.Deserialize(bytes.NewReader(txBytes))
	if err != nil {
		return nil, err
	}

	return &msgTx, nil
}
Example #3
0
// calcPriority returns a transaction priority given a transaction and the sum
// of each of its input values multiplied by their age (# of confirmations).
// Thus, the final formula for the priority is:
// sum(inputValue * inputAge) / adjustedTxSize
func calcPriority(tx *wire.MsgTx, utxoView *blockchain.UtxoViewpoint, nextBlockHeight int64) float64 {
	// In order to encourage spending multiple old unspent transaction
	// outputs thereby reducing the total set, don't count the constant
	// overhead for each input as well as enough bytes of the signature
	// script to cover a pay-to-script-hash redemption with a compressed
	// pubkey.  This makes additional inputs free by boosting the priority
	// of the transaction accordingly.  No more incentive is given to avoid
	// encouraging gaming future transactions through the use of junk
	// outputs.  This is the same logic used in the reference
	// implementation.
	//
	// The constant overhead for a txin is 41 bytes since the previous
	// outpoint is 36 bytes + 4 bytes for the sequence + 1 byte the
	// signature script length.
	//
	// A compressed pubkey pay-to-script-hash redemption with a maximum len
	// signature is of the form:
	// [OP_DATA_73 <73-byte sig> + OP_DATA_35 + {OP_DATA_33
	// <33 byte compresed pubkey> + OP_CHECKSIG}]
	//
	// Thus 1 + 73 + 1 + 1 + 33 + 1 = 110
	overhead := 0
	for _, txIn := range tx.TxIn {
		// Max inputs + size can't possibly overflow here.
		overhead += 41 + minInt(110, len(txIn.SignatureScript))
	}

	serializedTxSize := tx.SerializeSize()
	if overhead >= serializedTxSize {
		return 0.0
	}

	inputValueAge := calcInputValueAge(tx, utxoView, nextBlockHeight)
	return inputValueAge / float64(serializedTxSize-overhead)
}
// Receive waits for the response promised by the future and returns the
// signed transaction as well as whether or not all inputs are now signed.
func (r FutureSignRawTransactionResult) Receive() (*wire.MsgTx, bool, error) {
	res, err := receiveFuture(r)
	if err != nil {
		return nil, false, err
	}

	// Unmarshal as a signrawtransaction result.
	var signRawTxResult dcrjson.SignRawTransactionResult
	err = json.Unmarshal(res, &signRawTxResult)
	if err != nil {
		return nil, false, err
	}

	// Decode the serialized transaction hex to raw bytes.
	serializedTx, err := hex.DecodeString(signRawTxResult.Hex)
	if err != nil {
		return nil, false, err
	}

	// Deserialize the transaction and return it.
	var msgTx wire.MsgTx
	if err := msgTx.Deserialize(bytes.NewReader(serializedTx)); err != nil {
		return nil, false, err
	}

	return &msgTx, signRawTxResult.Complete, nil
}
Example #5
0
// fetchTxDataByLoc returns several pieces of data regarding the given tx
// located by the block/offset/size location
func (db *LevelDb) fetchTxDataByLoc(blkHeight int64, txOff int, txLen int, txspent []byte) (rtx *wire.MsgTx, rblksha *chainhash.Hash, rheight int64, rtxspent []byte, err error) {
	var blksha *chainhash.Hash
	var blkbuf []byte

	blksha, blkbuf, err = db.getBlkByHeight(blkHeight)
	if err != nil {
		if err == leveldb.ErrNotFound {
			err = database.ErrTxShaMissing
		}
		return
	}

	if len(blkbuf) < txOff+txLen {
		log.Warnf("block buffer overrun while looking for tx: "+
			"block %v %v txoff %v txlen %v", blkHeight, blksha, txOff, txLen)
		err = database.ErrDbInconsistency
		return
	}
	rbuf := bytes.NewReader(blkbuf[txOff : txOff+txLen])

	var tx wire.MsgTx
	err = tx.Deserialize(rbuf)
	if err != nil {
		log.Warnf("unable to decode tx block %v %v txoff %v txlen %v",
			blkHeight, blksha, txOff, txLen)
		err = database.ErrDbInconsistency
		return
	}

	return &tx, blksha, blkHeight, txspent, nil
}
// Receive waits for the response promised by the future and returns a
// transaction given its hash.
func (r FutureGetRawTransactionResult) Receive() (*dcrutil.Tx, error) {
	res, err := receiveFuture(r)
	if err != nil {
		return nil, err
	}

	// Unmarshal result as a string.
	var txHex string
	err = json.Unmarshal(res, &txHex)
	if err != nil {
		return nil, err
	}

	// Decode the serialized transaction hex to raw bytes.
	serializedTx, err := hex.DecodeString(txHex)
	if err != nil {
		return nil, err
	}

	// Deserialize the transaction and return it.
	var msgTx wire.MsgTx
	if err := msgTx.Deserialize(bytes.NewReader(serializedTx)); err != nil {
		return nil, err
	}
	return dcrutil.NewTx(&msgTx), nil
}
// Receive waits for the response promised by the future and returns the
// found raw transactions.
func (r FutureSearchRawTransactionsResult) Receive() ([]*wire.MsgTx, error) {
	res, err := receiveFuture(r)
	if err != nil {
		return nil, err
	}

	// Unmarshal as an array of strings.
	var searchRawTxnsResult []string
	err = json.Unmarshal(res, &searchRawTxnsResult)
	if err != nil {
		return nil, err
	}

	// Decode and deserialize each transaction.
	msgTxns := make([]*wire.MsgTx, 0, len(searchRawTxnsResult))
	for _, hexTx := range searchRawTxnsResult {
		// Decode the serialized transaction hex to raw bytes.
		serializedTx, err := hex.DecodeString(hexTx)
		if err != nil {
			return nil, err
		}

		// Deserialize the transaction and add it to the result slice.
		var msgTx wire.MsgTx
		err = msgTx.Deserialize(bytes.NewReader(serializedTx))
		if err != nil {
			return nil, err
		}
		msgTxns = append(msgTxns, &msgTx)
	}

	return msgTxns, nil
}
Example #8
0
// 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()
			}
		}
	}
}
Example #9
0
// deserializeSStxRecord deserializes the passed serialized tx record information.
func deserializeSStxRecord(serializedSStxRecord []byte) (*sstxRecord, error) {
	record := new(sstxRecord)

	curPos := 0

	// Read MsgTx size (as a uint64).
	msgTxLen := int(byteOrder.Uint64(
		serializedSStxRecord[curPos : curPos+int64Size]))
	curPos += int64Size

	// Pretend to read the pkScrLoc for the 0th output pkScript.
	curPos += int32Size

	// Read the intended voteBits and extended voteBits length (uint8).
	record.voteBitsSet = false
	voteBitsLen := uint8(serializedSStxRecord[curPos])
	if voteBitsLen != 0 {
		record.voteBitsSet = true
	}
	curPos += int8Size

	// Read the assumed 2 byte VoteBits as well as the extended
	// votebits (75 bytes max).
	record.voteBits = byteOrder.Uint16(
		serializedSStxRecord[curPos : curPos+int16Size])
	curPos += int16Size
	record.voteBitsExt = make([]byte, int(voteBitsLen)-int16Size)
	copy(record.voteBitsExt[:],
		serializedSStxRecord[curPos:curPos+int(voteBitsLen)-int16Size])
	curPos += stake.MaxSingleBytePushLength - int16Size

	// Prepare a buffer for the msgTx.
	buf := bytes.NewBuffer(serializedSStxRecord[curPos : curPos+msgTxLen])
	curPos += msgTxLen

	// Deserialize transaction.
	msgTx := new(wire.MsgTx)
	err := msgTx.Deserialize(buf)
	if err != nil {
		if err == io.EOF {
			err = io.ErrUnexpectedEOF
		}
		return nil, err
	}

	// Create and save the dcrutil.Tx of the read MsgTx and set its index.
	tx := dcrutil.NewTx((*wire.MsgTx)(msgTx))
	tx.SetIndex(dcrutil.TxIndexUnknown)
	tx.SetTree(dcrutil.TxTreeStake)
	record.tx = tx

	// Read received unix time (int64).
	received := int64(byteOrder.Uint64(
		serializedSStxRecord[curPos : curPos+int64Size]))
	curPos += int64Size
	record.ts = time.Unix(received, 0)

	return record, nil
}
Example #10
0
File: tx.go Project: decred/dcrutil
// NewTx returns a new instance of a transaction given an underlying
// wire.MsgTx.  See Tx.
func NewTx(msgTx *wire.MsgTx) *Tx {
	return &Tx{
		hash:    msgTx.TxHash(),
		msgTx:   msgTx,
		txTree:  wire.TxTreeUnknown,
		txIndex: TxIndexUnknown,
	}
}
Example #11
0
func spendOutput(txHash *chainhash.Hash, index uint32, outputValues ...int64) *wire.MsgTx {
	tx := wire.MsgTx{
		TxIn: []*wire.TxIn{
			&wire.TxIn{
				PreviousOutPoint: wire.OutPoint{Hash: *txHash, Index: index},
			},
		},
	}
	for _, val := range outputValues {
		tx.TxOut = append(tx.TxOut, &wire.TxOut{Value: val})
	}
	return &tx
}
Example #12
0
func newCoinBase(outputValues ...int64) *wire.MsgTx {
	tx := wire.MsgTx{
		TxIn: []*wire.TxIn{
			&wire.TxIn{
				PreviousOutPoint: wire.OutPoint{Index: ^uint32(0)},
			},
		},
	}
	for _, val := range outputValues {
		tx.TxOut = append(tx.TxOut, &wire.TxOut{Value: val})
	}
	return &tx
}
// SendRawTransactionAsync returns an instance of a type that can be used to get
// the result of the RPC at some future time by invoking the Receive function on
// the returned instance.
//
// See SendRawTransaction for the blocking version and more details.
func (c *Client) SendRawTransactionAsync(tx *wire.MsgTx, allowHighFees bool) FutureSendRawTransactionResult {
	txHex := ""
	if tx != nil {
		// Serialize the transaction and convert to hex string.
		buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
		if err := tx.Serialize(buf); err != nil {
			return newFutureError(err)
		}
		txHex = hex.EncodeToString(buf.Bytes())
	}

	cmd := dcrjson.NewSendRawTransactionCmd(txHex, &allowHighFees)
	return c.sendCmd(cmd)
}
Example #14
0
func equalTxs(t *testing.T, got, exp *wire.MsgTx) {
	var bufGot, bufExp bytes.Buffer
	err := got.Serialize(&bufGot)
	if err != nil {
		t.Fatal(err)
	}
	err = exp.Serialize(&bufExp)
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(bufGot.Bytes(), bufExp.Bytes()) {
		t.Errorf("Found unexpected wire.MsgTx:")
		t.Errorf("Got: %x", bufGot.Bytes())
		t.Errorf("Expected: %x", bufExp.Bytes())
	}
}
Example #15
0
File: tx.go Project: decred/dcrutil
// NewTxFromReader returns a new instance of a transaction given a
// Reader to deserialize the transaction.  See Tx.
func NewTxFromReader(r io.Reader) (*Tx, error) {
	// Deserialize the bytes into a MsgTx.
	var msgTx wire.MsgTx
	err := msgTx.Deserialize(r)
	if err != nil {
		return nil, err
	}

	t := Tx{
		hash:    msgTx.TxHash(),
		msgTx:   &msgTx,
		txTree:  wire.TxTreeUnknown,
		txIndex: TxIndexUnknown,
	}

	return &t, nil
}
Example #16
0
// BUGS:
// - The transaction is not inspected to be relevant before publishing using
//   sendrawtransaction, so connection errors to dcrd could result in the tx
//   never being added to the wallet database.
// - Once the above bug is fixed, wallet will require a way to purge invalid
//   transactions from the database when they are rejected by the network, other
//   than double spending them.
func (s *walletServer) PublishTransaction(ctx context.Context, req *pb.PublishTransactionRequest) (
	*pb.PublishTransactionResponse, error) {

	var msgTx wire.MsgTx
	err := msgTx.Deserialize(bytes.NewReader(req.SignedTransaction))
	if err != nil {
		return nil, grpc.Errorf(codes.InvalidArgument,
			"Bytes do not represent a valid raw transaction: %v", err)
	}

	txHash, err := s.wallet.PublishTransaction(&msgTx)
	if err != nil {
		return nil, translateError(err)
	}

	return &pb.PublishTransactionResponse{TransactionHash: txHash[:]}, nil
}
Example #17
0
File: tx.go Project: 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,
	}
}
Example #18
0
// BUGS:
// - InputIndexes request field is ignored.
func (s *walletServer) SignTransaction(ctx context.Context, req *pb.SignTransactionRequest) (
	*pb.SignTransactionResponse, error) {

	defer zero.Bytes(req.Passphrase)

	var tx wire.MsgTx
	err := tx.Deserialize(bytes.NewReader(req.SerializedTransaction))
	if err != nil {
		return nil, grpc.Errorf(codes.InvalidArgument,
			"Bytes do not represent a valid raw transaction: %v", err)
	}

	lock := make(chan time.Time, 1)
	defer func() {
		lock <- time.Time{} // send matters, not the value
	}()
	err = s.wallet.Unlock(req.Passphrase, lock)
	if err != nil {
		return nil, translateError(err)
	}

	invalidSigs, err := s.wallet.SignTransaction(&tx, txscript.SigHashAll, nil, nil, nil)
	if err != nil {
		return nil, translateError(err)
	}

	invalidInputIndexes := make([]uint32, len(invalidSigs))
	for i, e := range invalidSigs {
		invalidInputIndexes[i] = e.InputIndex
	}

	var serializedTransaction bytes.Buffer
	serializedTransaction.Grow(tx.SerializeSize())
	err = tx.Serialize(&serializedTransaction)
	if err != nil {
		return nil, translateError(err)
	}

	resp := &pb.SignTransactionResponse{
		Transaction:          serializedTransaction.Bytes(),
		UnsignedInputIndexes: invalidInputIndexes,
	}
	return resp, nil
}
Example #19
0
func TestStakeInvalidationOfTip(t *testing.T) {
	db, s, teardown, err := setup()
	defer teardown()
	if err != nil {
		t.Fatal(err)
	}

	g := makeBlockGenerator()
	block1Header := g.generate(dcrutil.BlockValid)
	block2Header := g.generate(dcrutil.BlockValid)
	block3Header := g.generate(0)

	block1Tx := wire.MsgTx{
		TxOut: []*wire.TxOut{{Value: 2e8}},
	}
	block2Tx := wire.MsgTx{
		TxIn: []*wire.TxIn{
			{PreviousOutPoint: wire.OutPoint{Hash: block1Tx.TxSha(), Index: 0, Tree: 0}},
		},
		TxOut: []*wire.TxOut{{Value: 1e8}},
	}
	block1TxRec, err := NewTxRecordFromMsgTx(&block1Tx, time.Time{})
	if err != nil {
		t.Fatal(err)
	}
	block2TxRec, err := NewTxRecordFromMsgTx(&block2Tx, time.Time{})
	if err != nil {
		t.Fatal(err)
	}

	const balanceFlag = BFBalanceSpendable

	err = walletdb.Update(db, func(tx walletdb.ReadWriteTx) error {
		ns := tx.ReadWriteBucket(wtxmgrNamespaceKey)
		addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)

		err := s.InsertMemPoolTx(ns, block1TxRec)
		if err != nil {
			return err
		}
		err = s.AddCredit(ns, block1TxRec, nil, 0, false, 0)
		if err != nil {
			return err
		}
		err = s.InsertMemPoolTx(ns, block2TxRec)
		if err != nil {
			return err
		}
		err = s.AddCredit(ns, block2TxRec, nil, 0, false, 0)
		if err != nil {
			return err
		}

		bal, err := s.Balance(ns, addrmgrNs, 0, balanceFlag, false, 0)
		if err != nil {
			return err
		}
		if bal != 1e8 {
			t.Errorf("Wrong balance before mining either transaction: %v", bal)
		}

		headerData := makeHeaderDataSlice(block1Header, block2Header)
		err = s.InsertMainChainHeaders(ns, addrmgrNs, headerData)
		if err != nil {
			return err
		}

		err = s.InsertMinedTx(ns, addrmgrNs, block1TxRec, &headerData[0].BlockHash)
		if err != nil {
			return err
		}
		err = s.InsertMinedTx(ns, addrmgrNs, block2TxRec, &headerData[1].BlockHash)
		if err != nil {
			return err
		}

		// At this point there should only be one credit for the tx in block 2.
		bal, err = s.Balance(ns, addrmgrNs, 1, balanceFlag, false, 0)
		if err != nil {
			return err
		}
		if bal != dcrutil.Amount(block2Tx.TxOut[0].Value) {
			t.Errorf("Wrong balance: expected %v got %v", dcrutil.Amount(block2Tx.TxOut[0].Value), bal)
		}
		credits, err := s.UnspentOutputs(ns)
		if err != nil {
			return err
		}
		if len(credits) != 1 {
			t.Errorf("Expected only 1 credit, got %v", len(credits))
			return nil
		}
		if credits[0].Hash != block2Tx.TxSha() {
			t.Errorf("Credit hash does match tx from block 2")
			return nil
		}
		if credits[0].Amount != dcrutil.Amount(block2Tx.TxOut[0].Value) {
			t.Errorf("Credit value does not match tx output 0 from block 2")
			return nil
		}

		// Add the next block header which invalidates the regular tx tree of
		// block 2.
		t.Log("Invalidating block 2")
		headerData = makeHeaderDataSlice(block3Header)
		err = s.InsertMainChainHeaders(ns, addrmgrNs, headerData)
		if err != nil {
			return err
		}
		/*
			d := makeHeaderData(block3Header)
			err = s.ExtendMainChain(ns, &d)
			if err != nil {
				return err
			}
		*/

		// Now the transaction in block 2 is invalidated.  There should only be
		// one unspent output, from block 1.
		bal, err = s.Balance(ns, addrmgrNs, 1, balanceFlag, false, 0)
		if err != nil {
			return err
		}
		if bal != dcrutil.Amount(block1Tx.TxOut[0].Value) {
			t.Errorf("Wrong balance: expected %v got %v", dcrutil.Amount(block1Tx.TxOut[0].Value), bal)
		}
		credits, err = s.UnspentOutputs(ns)
		if err != nil {
			return err
		}
		if len(credits) != 1 {
			t.Errorf("Expected only 1 credit, got %v", len(credits))
			return nil
		}
		if credits[0].Hash != block1Tx.TxSha() {
			t.Errorf("Credit hash does not match tx from block 1")
			return nil
		}
		if credits[0].Amount != dcrutil.Amount(block1Tx.TxOut[0].Value) {
			t.Errorf("Credit value does not match tx output 0 from block 1")
			return nil
		}

		return nil
	})
	if err != nil {
		t.Error(err)
	}
}
Example #20
0
var genesisCoinbaseTxLegacy = wire.MsgTx{
	Version: 1,
	TxIn: []*wire.TxIn{
		{
			PreviousOutPoint: wire.OutPoint{
				Hash:  chainhash.Hash{},
				Index: 0xffffffff,
			},
			SignatureScript: []byte{
				0x04, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, 0x45, /* |.......E| */
				0x54, 0x68, 0x65, 0x20, 0x54, 0x69, 0x6d, 0x65, /* |The Time| */
				0x73, 0x20, 0x30, 0x33, 0x2f, 0x4a, 0x61, 0x6e, /* |s 03/Jan| */
				0x2f, 0x32, 0x30, 0x30, 0x39, 0x20, 0x43, 0x68, /* |/2009 Ch| */
				0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x72, /* |ancellor| */
				0x20, 0x6f, 0x6e, 0x20, 0x62, 0x72, 0x69, 0x6e, /* | on brin| */
				0x6b, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x65, 0x63, /* |k of sec|*/
				0x6f, 0x6e, 0x64, 0x20, 0x62, 0x61, 0x69, 0x6c, /* |ond bail| */
				0x6f, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, /* |out for |*/
				0x62, 0x61, 0x6e, 0x6b, 0x73, /* |banks| */
			},
			Sequence: 0xffffffff,
		},
	},
	TxOut: []*wire.TxOut{
		{
			Value: 0x00000000,
			PkScript: []byte{
				0x41, 0x04, 0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, /* |A.g....U| */
				0x48, 0x27, 0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, /* |H'.g..q0| */
				0xb7, 0x10, 0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, /* |..\..(.9| */
				0x09, 0xa6, 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, /* |..yb...a| */
				0xde, 0xb6, 0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, /* |..I..?L.| */
				0x38, 0xc4, 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, /* |8..U....| */
				0x12, 0xde, 0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, /* |..\8M...| */
				0x8d, 0x57, 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, /* |.W.Lp+k.| */
				0x1d, 0x5f, 0xac, /* |._.| */
			},
		},
	},
	LockTime: 0,
	Expiry:   0,
}
Example #21
0
// TestTxSerializeWitnessValueSigning tests MsgTx serialize and deserialize.
func TestTxSerializeWitnessValueSigning(t *testing.T) {
	noTx := wire.NewMsgTx()
	noTx.Version = 262145
	noTxEncoded := []byte{
		0x01, 0x00, 0x04, 0x00, // Version
		0x00, // Varint for number of input signatures
	}

	tests := []struct {
		in           *wire.MsgTx // Message to encode
		out          *wire.MsgTx // Expected decoded message
		buf          []byte      // Serialized data
		pkScriptLocs []int       // Expected output script locations
	}{
		// No transactions.
		{
			noTx,
			noTx,
			noTxEncoded,
			nil,
		},

		// Multiple transactions.
		{
			multiTxWitnessValueSigning,
			multiTxWitnessValueSigning,
			multiTxWitnessValueSigningEncoded,
			nil,
		},
	}

	t.Logf("Running %d tests", len(tests))
	for i, test := range tests {
		// Serialize the transaction.
		var buf bytes.Buffer
		err := test.in.Serialize(&buf)
		if err != nil {
			t.Errorf("Serialize #%d error %v", i, err)
			continue
		}
		if !bytes.Equal(buf.Bytes(), test.buf) {
			t.Errorf("Serialize #%d\n got: %s want: %s", i,
				spew.Sdump(buf.Bytes()), spew.Sdump(test.buf))
			continue
		}

		// Test SerializeSize.
		sz := test.in.SerializeSize()
		actualSz := len(buf.Bytes())
		if sz != actualSz {
			t.Errorf("Wrong serialize size #%d\n got: %s want: %s", i,
				sz, actualSz)
		}

		// Deserialize the transaction.
		var tx wire.MsgTx
		rbuf := bytes.NewReader(test.buf)
		err = tx.Deserialize(rbuf)
		if err != nil {
			t.Errorf("Deserialize #%d error %v", i, err)
			continue
		}
		if !reflect.DeepEqual(&tx, test.out) {
			t.Errorf("Deserialize #%d\n got: %s want: %s", i,
				spew.Sdump(&tx), spew.Sdump(test.out))
			continue
		}

		// Ensure the public key script locations are accurate.
		pkScriptLocs := test.in.PkScriptLocs()
		if !reflect.DeepEqual(pkScriptLocs, test.pkScriptLocs) {
			t.Errorf("PkScriptLocs #%d\n got: %s want: %s", i,
				spew.Sdump(pkScriptLocs),
				spew.Sdump(test.pkScriptLocs))
			continue
		}
		for j, loc := range pkScriptLocs {
			wantPkScript := test.in.TxOut[j].PkScript
			gotPkScript := test.buf[loc : loc+len(wantPkScript)]
			if !bytes.Equal(gotPkScript, wantPkScript) {
				t.Errorf("PkScriptLocs #%d:%d\n unexpected "+
					"script got: %s want: %s", i, j,
					spew.Sdump(gotPkScript),
					spew.Sdump(wantPkScript))
			}
		}
	}
}
Example #22
0
// TestTxSerializeErrors performs negative tests against wire encode and decode
// of MsgTx to confirm error paths work correctly.
func TestTxSerializeErrors(t *testing.T) {
	tests := []struct {
		in       *wire.MsgTx // Value to encode
		buf      []byte      // Serialized data
		max      int         // Max size of fixed buffer to induce errors
		writeErr error       // Expected write error
		readErr  error       // Expected read error
	}{
		// Force error in version.
		{multiTx, multiTxEncoded, 0, io.ErrShortWrite, io.EOF},
		// Force error in number of transaction inputs.
		{multiTx, multiTxEncoded, 4, io.ErrShortWrite, io.EOF},
		// Force error in transaction input previous block hash.
		{multiTx, multiTxEncoded, 5, io.ErrShortWrite, io.EOF},
		// Force error in transaction input previous block output index.
		{multiTx, multiTxEncoded, 37, io.ErrShortWrite, io.EOF},
		// Force error in transaction input previous block output tree.
		{multiTx, multiTxEncoded, 41, io.ErrShortWrite, io.EOF},
		// Force error in transaction input sequence.
		{multiTx, multiTxEncoded, 42, io.ErrShortWrite, io.EOF},
		// Force error in number of transaction outputs.
		{multiTx, multiTxEncoded, 46, io.ErrShortWrite, io.EOF},
		// Force error in transaction output value.
		{multiTx, multiTxEncoded, 47, io.ErrShortWrite, io.EOF},
		// Force error in transaction output version.
		{multiTx, multiTxEncoded, 55, io.ErrShortWrite, io.EOF},
		// Force error in transaction output pk script length.
		{multiTx, multiTxEncoded, 57, io.ErrShortWrite, io.EOF},
		// Force error in transaction output pk script.
		{multiTx, multiTxEncoded, 58, io.ErrShortWrite, io.EOF},
		// Force error in transaction lock time.
		{multiTx, multiTxEncoded, 203, io.ErrShortWrite, io.EOF},
		// Force error in transaction expiry.
		{multiTx, multiTxEncoded, 207, io.ErrShortWrite, io.EOF},
		// Force error in transaction num sig varint.
		{multiTx, multiTxEncoded, 211, io.ErrShortWrite, io.EOF},
		// Force error in transaction sig 0 ValueIn.
		{multiTx, multiTxEncoded, 212, io.ErrShortWrite, io.EOF},
		// Force error in transaction sig 0 BlockHeight.
		{multiTx, multiTxEncoded, 220, io.ErrShortWrite, io.EOF},
		// Force error in transaction sig 0 BlockIndex.
		{multiTx, multiTxEncoded, 224, io.ErrShortWrite, io.EOF},
		// Force error in transaction sig 0 length.
		{multiTx, multiTxEncoded, 228, io.ErrShortWrite, io.EOF},
		// Force error in transaction sig 0 signature script.
		{multiTx, multiTxEncoded, 229, io.ErrShortWrite, io.EOF},
	}

	t.Logf("Running %d tests", len(tests))
	for i, test := range tests {
		// Serialize the transaction.
		w := newFixedWriter(test.max)
		err := test.in.Serialize(w)
		if err != test.writeErr {
			t.Errorf("Serialize #%d wrong error got: %v, want: %v",
				i, err, test.writeErr)
			continue
		}

		// Deserialize the transaction.
		var tx wire.MsgTx
		r := newFixedReader(test.max, test.buf)
		err = tx.Deserialize(r)
		if err != test.readErr {
			t.Errorf("Deserialize #%d wrong error got: %v, want: %v",
				i, err, test.readErr)
			continue
		}
	}
}
Example #23
0
// TestTxOverflowErrors performs tests to ensure deserializing transactions
// which are intentionally crafted to use large values for the variable number
// of inputs and outputs are handled properly.  This could otherwise potentially
// be used as an attack vector.
func TestTxOverflowErrors(t *testing.T) {
	// Use protocol version 1 and transaction version 1 specifically
	// here instead of the latest values because the test data is using
	// bytes encoded with those versions.
	pver := uint32(1)
	txVer := wire.DefaultMsgTxVersion()

	tests := []struct {
		buf     []byte // Wire encoding
		pver    uint32 // Protocol version for wire encoding
		version int32  // Transaction version
		err     error  // Expected error
	}{
		// Transaction that claims to have ~uint64(0) inputs. [0]
		{
			[]byte{
				0x01, 0x00, 0x00, 0x00, // Version
				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
				0xff, // Varint for number of input transactions
			}, pver, txVer, &wire.MessageError{},
		},

		// Transaction that claims to have ~uint64(0) outputs. [1]
		{
			[]byte{
				0x01, 0x00, 0x00, 0x00, // Version
				0x00, // Varint for number of input transactions
				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
				0xff, // Varint for number of output transactions
			}, pver, txVer, &wire.MessageError{},
		},

		// Transaction that has an input with a signature script that [2]
		// claims to have ~uint64(0) length.
		{
			[]byte{
				0x01, 0x00, 0x00, 0x00, // Version
				0x01, // Varint for number of input transactions
				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Previous output hash
				0xff, 0xff, 0xff, 0xff, // Previous output index
				0x00,                   // Previous output tree
				0x00,                   // Varint for length of signature script
				0xff, 0xff, 0xff, 0xff, // Sequence
				0x02,                                           // Varint for number of output transactions
				0x00, 0xf2, 0x05, 0x2a, 0x01, 0x00, 0x00, 0x00, // Transaction amount
				0x43, // Varint for length of pk script
				0x41, // OP_DATA_65
				0x04, 0xd6, 0x4b, 0xdf, 0xd0, 0x9e, 0xb1, 0xc5,
				0xfe, 0x29, 0x5a, 0xbd, 0xeb, 0x1d, 0xca, 0x42,
				0x81, 0xbe, 0x98, 0x8e, 0x2d, 0xa0, 0xb6, 0xc1,
				0xc6, 0xa5, 0x9d, 0xc2, 0x26, 0xc2, 0x86, 0x24,
				0xe1, 0x81, 0x75, 0xe8, 0x51, 0xc9, 0x6b, 0x97,
				0x3d, 0x81, 0xb0, 0x1c, 0xc3, 0x1f, 0x04, 0x78,
				0x34, 0xbc, 0x06, 0xd6, 0xd6, 0xed, 0xf6, 0x20,
				0xd1, 0x84, 0x24, 0x1a, 0x6a, 0xed, 0x8b, 0x63,
				0xa6,                                           // 65-byte signature
				0xac,                                           // OP_CHECKSIG
				0x00, 0xe1, 0xf5, 0x05, 0x00, 0x00, 0x00, 0x00, // Transaction amount
				0x43, // Varint for length of pk script
				0x41, // OP_DATA_65
				0x04, 0xd6, 0x4b, 0xdf, 0xd0, 0x9e, 0xb1, 0xc5,
				0xfe, 0x29, 0x5a, 0xbd, 0xeb, 0x1d, 0xca, 0x42,
				0x81, 0xbe, 0x98, 0x8e, 0x2d, 0xa0, 0xb6, 0xc1,
				0xc6, 0xa5, 0x9d, 0xc2, 0x26, 0xc2, 0x86, 0x24,
				0xe1, 0x81, 0x75, 0xe8, 0x51, 0xc9, 0x6b, 0x97,
				0x3d, 0x81, 0xb0, 0x1c, 0xc3, 0x1f, 0x04, 0x78,
				0x34, 0xbc, 0x06, 0xd6, 0xd6, 0xed, 0xf6, 0x20,
				0xd1, 0x84, 0x24, 0x1a, 0x6a, 0xed, 0x8b, 0x63,
				0xa6,                   // 65-byte signature
				0xac,                   // OP_CHECKSIG
				0x00, 0x00, 0x00, 0x00, // Lock time
				0x00, 0x00, 0x00, 0x00, // Expiry
				0x01,                                                 // Varint for number of input signature
				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // Varint for sig script length (overflows)
			}, pver, txVer, &wire.MessageError{},
		},

		// Transaction that has an output with a public key script [3]
		// that claims to have ~uint64(0) length.
		{
			[]byte{
				0x01, 0x00, 0x00, 0x00, // Version
				0x01, // Varint for number of input transactions
				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Previous output hash
				0xff, 0xff, 0xff, 0xff, // Prevous output index
				0x00,                   // Previous output tree
				0x00,                   // Varint for length of signature script
				0xff, 0xff, 0xff, 0xff, // Sequence
				0x01,                                           // Varint for number of output transactions
				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Transaction amount
				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
				0xff, // Varint for length of public key script
			}, pver, txVer, &wire.MessageError{},
		},
	}

	t.Logf("Running %d tests", len(tests))
	for i, test := range tests {
		// Decode from wire format.
		var msg wire.MsgTx
		r := bytes.NewReader(test.buf)
		err := msg.BtcDecode(r, test.pver)
		if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
			t.Errorf("BtcDecode #%d wrong error got: %v, want: %v",
				i, err, reflect.TypeOf(test.err))
		}

		// Decode from wire format.
		r = bytes.NewReader(test.buf)
		err = msg.Deserialize(r)
		if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
			t.Errorf("Deserialize #%d wrong error got: %v, want: %v",
				i, err, reflect.TypeOf(test.err))
			continue
		}
	}
}
Example #24
0
// DebugMsgTxString dumps a verbose message containing information about the
// contents of a transaction.
func DebugMsgTxString(msgTx *wire.MsgTx) string {
	tx := dcrutil.NewTx(msgTx)
	isSStx, _ := stake.IsSStx(tx)
	isSSGen, _ := stake.IsSSGen(tx)
	var sstxType []bool
	var sstxPkhs [][]byte
	var sstxAmts []int64
	var sstxRules [][]bool
	var sstxLimits [][]uint16

	if isSStx {
		sstxType, sstxPkhs, sstxAmts, _, sstxRules, sstxLimits =
			stake.GetSStxStakeOutputInfo(tx)
	}

	var buffer bytes.Buffer

	hash := msgTx.TxSha()
	str := fmt.Sprintf("Transaction hash: %v, Version %v, Locktime: %v, "+
		"Expiry %v\n\n", hash, msgTx.Version, msgTx.LockTime, msgTx.Expiry)
	buffer.WriteString(str)

	str = fmt.Sprintf("==INPUTS==\nNumber of inputs: %v\n\n",
		len(msgTx.TxIn))
	buffer.WriteString(str)

	for i, input := range msgTx.TxIn {
		str = fmt.Sprintf("Input number: %v\n", i)
		buffer.WriteString(str)

		str = fmt.Sprintf("Previous outpoint hash: %v, ",
			input.PreviousOutPoint.Hash)
		buffer.WriteString(str)

		str = fmt.Sprintf("Previous outpoint index: %v, ",
			input.PreviousOutPoint.Index)
		buffer.WriteString(str)

		str = fmt.Sprintf("Previous outpoint tree: %v \n",
			input.PreviousOutPoint.Tree)
		buffer.WriteString(str)

		str = fmt.Sprintf("Sequence: %v \n",
			input.Sequence)
		buffer.WriteString(str)

		str = fmt.Sprintf("ValueIn: %v \n",
			input.ValueIn)
		buffer.WriteString(str)

		str = fmt.Sprintf("BlockHeight: %v \n",
			input.BlockHeight)
		buffer.WriteString(str)

		str = fmt.Sprintf("BlockIndex: %v \n",
			input.BlockIndex)
		buffer.WriteString(str)

		str = fmt.Sprintf("Raw signature script: %x \n", input.SignatureScript)
		buffer.WriteString(str)

		sigScr, _ := txscript.DisasmString(input.SignatureScript)
		str = fmt.Sprintf("Disasmed signature script: %v \n\n",
			sigScr)
		buffer.WriteString(str)
	}

	str = fmt.Sprintf("==OUTPUTS==\nNumber of outputs: %v\n\n",
		len(msgTx.TxOut))
	buffer.WriteString(str)

	for i, output := range msgTx.TxOut {
		str = fmt.Sprintf("Output number: %v\n", i)
		buffer.WriteString(str)

		coins := float64(output.Value) / 1e8
		str = fmt.Sprintf("Output amount: %v atoms or %v coins\n", output.Value,
			coins)
		buffer.WriteString(str)

		// SStx OP_RETURNs, dump pkhs and amts committed
		if isSStx && i != 0 && i%2 == 1 {
			coins := float64(sstxAmts[i/2]) / 1e8
			str = fmt.Sprintf("SStx commit amount: %v atoms or %v coins\n",
				sstxAmts[i/2], coins)
			buffer.WriteString(str)
			str = fmt.Sprintf("SStx commit address: %x\n",
				sstxPkhs[i/2])
			buffer.WriteString(str)
			str = fmt.Sprintf("SStx address type is P2SH: %v\n",
				sstxType[i/2])
			buffer.WriteString(str)

			str = fmt.Sprintf("SStx all address types is P2SH: %v\n",
				sstxType)
			buffer.WriteString(str)

			str = fmt.Sprintf("Voting is fee limited: %v\n",
				sstxLimits[i/2][0])
			buffer.WriteString(str)
			if sstxRules[i/2][0] {
				str = fmt.Sprintf("Voting limit imposed: %v\n",
					sstxLimits[i/2][0])
				buffer.WriteString(str)
			}

			str = fmt.Sprintf("Revoking is fee limited: %v\n",
				sstxRules[i/2][1])
			buffer.WriteString(str)

			if sstxRules[i/2][1] {
				str = fmt.Sprintf("Voting limit imposed: %v\n",
					sstxLimits[i/2][1])
				buffer.WriteString(str)
			}
		}

		// SSGen block/block height OP_RETURN.
		if isSSGen && i == 0 {
			blkHash, blkHeight, _ := stake.GetSSGenBlockVotedOn(tx)
			str = fmt.Sprintf("SSGen block hash voted on: %v, height: %v\n",
				blkHash, blkHeight)
			buffer.WriteString(str)
		}

		if isSSGen && i == 1 {
			vb := stake.GetSSGenVoteBits(tx)
			str = fmt.Sprintf("SSGen vote bits: %v\n", vb)
			buffer.WriteString(str)
		}

		str = fmt.Sprintf("Raw script: %x \n", output.PkScript)
		buffer.WriteString(str)

		scr, _ := txscript.DisasmString(output.PkScript)
		str = fmt.Sprintf("Disasmed script: %v \n\n", scr)
		buffer.WriteString(str)
	}

	return buffer.String()
}
Example #25
0
// calcSignatureHash will, given a script and hash type for the current script
// engine instance, calculate the signature hash to be used for signing and
// verification.
func calcSignatureHash(script []parsedOpcode, hashType SigHashType,
	tx *wire.MsgTx, idx int, cachedPrefix *chainhash.Hash) ([]byte, error) {
	// The SigHashSingle signature type signs only the corresponding input
	// and output (the output with the same index number as the input).
	//
	// Since transactions can have more inputs than outputs, this means it
	// is improper to use SigHashSingle on input indices that don't have a
	// corresponding output.
	//
	// A bug in the original Satoshi client implementation means specifying
	// an index that is out of range results in a signature hash of 1 (as a
	// uint256 little endian).  The original intent appeared to be to
	// indicate failure, but unfortunately, it was never checked and thus is
	// treated as the actual signature hash.  This buggy behavior is now
	// part of the consensus and a hard fork would be required to fix it.
	//
	// Due to this, care must be taken by software that creates transactions
	// which make use of SigHashSingle because it can lead to an extremely
	// dangerous situation where the invalid inputs will end up signing a
	// hash of 1.  This in turn presents an opportunity for attackers to
	// cleverly construct transactions which can steal those coins provided
	// they can reuse signatures.
	//
	// Decred mitigates this by actually returning an error instead.
	if hashType&sigHashMask == SigHashSingle && idx >= len(tx.TxOut) {
		return nil, ErrSighashSingleIdx
	}

	// Remove all instances of OP_CODESEPARATOR from the script.
	script = removeOpcode(script, OP_CODESEPARATOR)

	// Make a deep copy of the transaction, zeroing out the script for all
	// inputs that are not currently being processed.
	txCopy := tx.Copy()
	for i := range txCopy.TxIn {
		if i == idx {
			// UnparseScript cannot fail here because removeOpcode
			// above only returns a valid script.
			sigScript, _ := unparseScript(script)
			txCopy.TxIn[idx].SignatureScript = sigScript
		} else {
			txCopy.TxIn[i].SignatureScript = nil
		}
	}

	switch hashType & sigHashMask {
	case SigHashNone:
		txCopy.TxOut = txCopy.TxOut[0:0] // Empty slice.
		for i := range txCopy.TxIn {
			if i != idx {
				txCopy.TxIn[i].Sequence = 0
			}
		}

	case SigHashSingle:
		// Resize output array to up to and including requested index.
		txCopy.TxOut = txCopy.TxOut[:idx+1]

		// All but current output get zeroed out.
		for i := 0; i < idx; i++ {
			txCopy.TxOut[i].Value = -1
			txCopy.TxOut[i].PkScript = nil
		}

		// Sequence on all other inputs is 0, too.
		for i := range txCopy.TxIn {
			if i != idx {
				txCopy.TxIn[i].Sequence = 0
			}
		}

	default:
		// Consensus treats undefined hashtypes like normal SigHashAll
		// for purposes of hash generation.
		fallthrough
	case SigHashOld:
		fallthrough
	case SigHashAllValue:
		fallthrough
	case SigHashAll:
		// Nothing special here.
	}
	if hashType&SigHashAnyOneCanPay != 0 {
		txCopy.TxIn = txCopy.TxIn[idx : idx+1]
		idx = 0
	}

	// The final hash (message to sign) is the hash of:
	// 1) hash of the prefix ||
	// 2) hash of the witness for signing ||
	// 3) the hash type (encoded as a 4-byte little-endian value)
	var wbuf bytes.Buffer
	binary.Write(&wbuf, binary.LittleEndian, uint32(hashType))

	// Optimization for SIGHASH_ALL. In this case, the prefix hash is
	// the same as the transaction hash because only the inputs have
	// been modified, so don't bother to do the wasteful O(N^2) extra
	// hash here.
	// The caching only works if the "anyone can pay flag" is also
	// disabled.
	var prefixHash chainhash.Hash
	if cachedPrefix != nil &&
		(hashType&sigHashMask == SigHashAll) &&
		(hashType&SigHashAnyOneCanPay == 0) &&
		chaincfg.SigHashOptimization {
		prefixHash = *cachedPrefix
	} else {
		prefixHash = txCopy.TxSha()
	}

	// If the ValueIn is to be included in what we're signing, sign
	// the witness hash that includes it. Otherwise, just sign the
	// prefix and signature scripts.
	var witnessHash chainhash.Hash
	if hashType&sigHashMask != SigHashAllValue {
		witnessHash = txCopy.TxShaWitnessSigning()
	} else {
		witnessHash = txCopy.TxShaWitnessValueSigning()
	}
	wbuf.Write(prefixHash.Bytes())
	wbuf.Write(witnessHash.Bytes())
	return chainhash.HashFuncB(wbuf.Bytes()), nil
}
Example #26
0
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)
	}
}
Example #27
0
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())
		}
	}
}
Example #28
0
var genesisCoinbaseTx = wire.MsgTx{
	Version: 1,
	TxIn: []*wire.TxIn{
		{
			// Fully null.
			PreviousOutPoint: wire.OutPoint{
				Hash:  chainhash.Hash{},
				Index: 0xffffffff,
				Tree:  0,
			},
			SignatureScript: []byte{
				0x00, 0x00,
			},
			Sequence:    0xffffffff,
			BlockHeight: wire.NullBlockHeight,
			BlockIndex:  wire.NullBlockIndex,
			ValueIn:     wire.NullValueIn,
		},
	},
	TxOut: []*wire.TxOut{
		{
			Version: 0x0000,
			Value:   0x00000000,
			PkScript: []byte{
				0x80, 0x16, 0x79, 0xe9, 0x85, 0x61, 0xad, 0xa9,
				0x6c, 0xae, 0xc2, 0x94, 0x9a, 0x5d, 0x41, 0xc4,
				0xca, 0xb3, 0x85, 0x1e, 0xb7, 0x40, 0xd9, 0x51,
				0xc1, 0x0e, 0xcb, 0xcf, 0x26, 0x5c, 0x1f, 0xd9,
			},
		},
	},
	LockTime: 0,
	Expiry:   0,
}
Example #29
0
func TestStakeInvalidationTxInsert(t *testing.T) {
	db, s, teardown, err := setup()
	defer teardown()
	if err != nil {
		t.Fatal(err)
	}

	g := makeBlockGenerator()
	block1Header := g.generate(dcrutil.BlockValid)
	block2Header := g.generate(dcrutil.BlockValid)
	block3Header := g.generate(0)

	block1Tx := wire.MsgTx{
		TxOut: []*wire.TxOut{{Value: 2e8}},
	}
	block2Tx := wire.MsgTx{
		TxIn: []*wire.TxIn{
			{PreviousOutPoint: wire.OutPoint{Hash: block1Tx.TxSha(), Index: 0, Tree: 0}},
		},
		TxOut: []*wire.TxOut{{Value: 1e8}},
	}
	block1TxRec, err := NewTxRecordFromMsgTx(&block1Tx, time.Time{})
	if err != nil {
		t.Fatal(err)
	}
	block2TxRec, err := NewTxRecordFromMsgTx(&block2Tx, time.Time{})
	if err != nil {
		t.Fatal(err)
	}

	err = walletdb.Update(db, func(tx walletdb.ReadWriteTx) error {
		ns := tx.ReadWriteBucket(wtxmgrNamespaceKey)
		addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)

		headerData := makeHeaderDataSlice(block1Header, block2Header, block3Header)
		err = s.InsertMainChainHeaders(ns, addrmgrNs, headerData)
		if err != nil {
			return err
		}

		err = s.InsertMinedTx(ns, addrmgrNs, block1TxRec, &headerData[0].BlockHash)
		if err != nil {
			return err
		}
		err = s.AddCredit(ns, block1TxRec, makeBlockMeta(block1Header), 0, false, 0)
		if err != nil {
			return err
		}
		err = s.InsertMinedTx(ns, addrmgrNs, block2TxRec, &headerData[1].BlockHash)
		if err != nil {
			return err
		}
		err = s.AddCredit(ns, block2TxRec, makeBlockMeta(block2Header), 0, false, 0)
		if err != nil {
			return err
		}

		// The transaction in block 2 was inserted invalidated.  There should
		// only be one unspent output, from block 1.
		bal, err := s.Balance(ns, addrmgrNs, 1, BFBalanceFullScan, true, 0)
		if err != nil {
			return err
		}
		if bal != dcrutil.Amount(block1Tx.TxOut[0].Value) {
			t.Errorf("Wrong balance: expected %v got %v", dcrutil.Amount(block1Tx.TxOut[0].Value), bal)
		}
		bal, err = s.Balance(ns, addrmgrNs, 1, BFBalanceSpendable, true, 0)
		if err != nil {
			return err
		}
		if bal != dcrutil.Amount(block1Tx.TxOut[0].Value) {
			t.Errorf("Wrong balance: expected %v got %v", dcrutil.Amount(block1Tx.TxOut[0].Value), bal)
		}
		credits, err := s.UnspentOutputs(ns)
		if err != nil {
			return err
		}
		if len(credits) != 1 {
			t.Errorf("Expected only 1 credit, got %v", len(credits))
			return nil
		}
		if credits[0].Hash != block1Tx.TxSha() {
			t.Errorf("Credit hash does not match tx from block 1")
			return nil
		}
		if credits[0].Amount != dcrutil.Amount(block1Tx.TxOut[0].Value) {
			t.Errorf("Credit value does not match tx output 0 from block 1")
			return nil
		}

		return nil
	})
	if err != nil {
		t.Error(err)
	}
}
Example #30
0
// TestTxWireErrors performs negative tests against wire encode and decode
// of MsgTx to confirm error paths work correctly.
func TestTxWireErrors(t *testing.T) {
	// Use protocol version 60002 specifically here instead of the latest
	// because the test data is using bytes encoded with that protocol
	// version.
	pver := uint32(60002)

	tests := []struct {
		in       *wire.MsgTx // Value to encode
		buf      []byte      // Wire encoding
		pver     uint32      // Protocol version for wire encoding
		max      int         // Max size of fixed buffer to induce errors
		writeErr error       // Expected write error
		readErr  error       // Expected read error
	}{
		// Force error in version.
		{multiTx, multiTxEncoded, pver, 0, io.ErrShortWrite, io.EOF}, // 0
		// Force error in number of transaction inputs.
		{multiTx, multiTxEncoded, pver, 4, io.ErrShortWrite, io.EOF}, // 1
		// Force error in transaction input previous block hash.
		{multiTx, multiTxEncoded, pver, 5, io.ErrShortWrite, io.EOF}, // 2
		// Force error in transaction input previous block output index.
		{multiTx, multiTxEncoded, pver, 37, io.ErrShortWrite, io.EOF}, // 3
		// Force error in transaction input previous block output tree.
		{multiTx, multiTxEncoded, pver, 41, io.ErrShortWrite, io.EOF}, // 4
		// Force error in transaction input sequence.
		{multiTx, multiTxEncoded, pver, 42, io.ErrShortWrite, io.EOF}, // 5
		// Force error in number of transaction outputs.
		{multiTx, multiTxEncoded, pver, 46, io.ErrShortWrite, io.EOF}, // 6
		// Force error in transaction output value.
		{multiTx, multiTxEncoded, pver, 47, io.ErrShortWrite, io.EOF}, // 7
		// Force error in transaction output script version.
		{multiTx, multiTxEncoded, pver, 55, io.ErrShortWrite, io.EOF}, // 8
		// Force error in transaction output pk script length.
		{multiTx, multiTxEncoded, pver, 57, io.ErrShortWrite, io.EOF}, // 9
		// Force error in transaction output pk script.
		{multiTx, multiTxEncoded, pver, 58, io.ErrShortWrite, io.EOF}, // 10
		// Force error in transaction output lock time.
		{multiTx, multiTxEncoded, pver, 203, io.ErrShortWrite, io.EOF}, // 11
		// Force error in transaction output expiry.
		{multiTx, multiTxEncoded, pver, 207, io.ErrShortWrite, io.EOF}, // 12
		// Force error in transaction num sig varint.
		{multiTx, multiTxEncoded, pver, 211, io.ErrShortWrite, io.EOF}, // 13
		// Force error in transaction sig 0 AmountIn.
		{multiTx, multiTxEncoded, pver, 212, io.ErrShortWrite, io.EOF}, // 14
		// Force error in transaction sig 0 BlockHeight.
		{multiTx, multiTxEncoded, pver, 220, io.ErrShortWrite, io.EOF}, // 15
		// Force error in transaction sig 0 BlockIndex.
		{multiTx, multiTxEncoded, pver, 224, io.ErrShortWrite, io.EOF}, // 16
		// Force error in transaction sig 0 length.
		{multiTx, multiTxEncoded, pver, 228, io.ErrShortWrite, io.EOF}, // 17
		// Force error in transaction sig 0 signature script.
		{multiTx, multiTxEncoded, pver, 229, io.ErrShortWrite, io.EOF}, // 18
	}

	t.Logf("Running %d tests", len(tests))
	for i, test := range tests {
		// Encode to wire format.
		w := newFixedWriter(test.max)
		err := test.in.BtcEncode(w, test.pver)
		if err != test.writeErr {
			t.Errorf("BtcEncode #%d wrong error got: %v, want: %v",
				i, err, test.writeErr)
			continue
		}

		// Decode from wire format.
		var msg wire.MsgTx
		r := newFixedReader(test.max, test.buf)
		err = msg.BtcDecode(r, test.pver)
		if err != test.readErr {
			t.Errorf("BtcDecode #%d wrong error got: %v, want: %v",
				i, err, test.readErr)
			continue
		}
	}
}