Example #1
0
// maybeAddOrphan potentially adds an orphan to the orphan pool.
func (mp *txMemPool) maybeAddOrphan(tx *btcwire.MsgTx, txHash *btcwire.ShaHash) error {
	// Ignore orphan transactions that are too large.  This helps avoid
	// a memory exhaustion attack based on sending a lot of really large
	// orphans.  In the case there is a valid transaction larger than this,
	// it will ultimtely be rebroadcast after the parent transactions
	// have been mined or otherwise received.
	//
	// Note that the number of orphan transactions in the orphan pool is
	// also limited, so this equates to a maximum memory used of
	// maxOrphanTxSize * maxOrphanTransactions (which is 500MB as of the
	// time this comment was written).
	var serializedTxBuf bytes.Buffer
	err := tx.Serialize(&serializedTxBuf)
	if err != nil {
		return err
	}
	serializedLen := serializedTxBuf.Len()
	if serializedLen > maxOrphanTxSize {
		str := fmt.Sprintf("orphan transaction size of %d bytes is "+
			"larger than max allowed size of %d bytes",
			serializedLen, maxOrphanTxSize)
		return TxRuleError(str)
	}

	// Add the orphan if the none of the above disqualified it.
	mp.addOrphan(tx, txHash)

	return nil
}
Example #2
0
// 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 *btcwire.MsgTx, inputs []btcjson.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())
	}

	id := c.NextID()
	cmd, err := btcjson.NewSignRawTransactionCmd(id, txHex, inputs)
	if err != nil {
		return newFutureError(err)
	}

	return c.sendCmd(cmd)
}
Example #3
0
// checkTransactionStandard performs a series of checks on a transaction to
// ensure it is a "standard" transaction.  A standard transaction is one that
// conforms to several additional limiting cases over what is considered a
// "sane" transaction such as having a version in the supported range, being
// finalized, conforming to more stringent size constraints, having scripts
// of recognized forms, and not containing "dust" outputs (those that are
// so small it costs more to process them than they are worth).
func checkTransactionStandard(tx *btcwire.MsgTx, height int64) error {
	// The transaction must be a currently supported version.
	if tx.Version > btcwire.TxVersion || tx.Version < 1 {
		str := fmt.Sprintf("transaction version %d is not in the "+
			"valid range of %d-%d", tx.Version, 1,
			btcwire.TxVersion)
		return TxRuleError(str)
	}

	// The transaction must be finalized to be standard and therefore
	// considered for inclusion in a block.
	if !btcchain.IsFinalizedTransaction(tx, height, time.Now()) {
		str := fmt.Sprintf("transaction is not finalized")
		return TxRuleError(str)
	}

	// Since extremely large transactions with a lot of inputs can cost
	// almost as much to process as the sender fees, limit the maximum
	// size of a transaction.  This also helps mitigate CPU exhaustion
	// attacks.
	var serializedTxBuf bytes.Buffer
	err := tx.Serialize(&serializedTxBuf)
	if err != nil {
		return err
	}
	serializedLen := serializedTxBuf.Len()
	if serializedLen > maxStandardTxSize {
		str := fmt.Sprintf("transaction size of %v is larger than max "+
			"allowed size of %v", serializedLen, maxStandardTxSize)
		return TxRuleError(str)
	}

	for i, txIn := range tx.TxIn {
		// Each transaction input signature script must not exceed the
		// maximum size allowed for a standard transaction.  See
		// the comment on maxStandardSigScriptSize for more details.
		sigScriptLen := len(txIn.SignatureScript)
		if sigScriptLen > maxStandardSigScriptSize {
			str := fmt.Sprintf("transaction input %d: signature "+
				"script size of %d bytes is large than max "+
				"allowed size of %d bytes", i, sigScriptLen,
				maxStandardSigScriptSize)
			return TxRuleError(str)
		}

		// Each transaction input signature script must only contain
		// opcodes which push data onto the stack.
		if !btcscript.IsPushOnlyScript(txIn.SignatureScript) {
			str := fmt.Sprintf("transaction input %d: signature "+
				"script is not push only", i)
			return TxRuleError(str)
		}
	}

	// None of the output public key scripts can be a non-standard script or
	// be "dust".
	for i, txOut := range tx.TxOut {
		err := checkPkScriptStandard(txOut.PkScript)
		if err != nil {
			str := fmt.Sprintf("transaction output %d: %v", i, err)
			return TxRuleError(str)
		}

		if isDust(txOut) {
			str := fmt.Sprintf("transaction output %d: payment "+
				"of %d is dust", i, txOut.Value)
			return TxRuleError(str)
		}
	}

	return nil
}
Example #4
0
// toHex converts a msgTx into a hex string.
func ToHex(tx *btcwire.MsgTx) string {
	buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
	tx.Serialize(buf)
	txHex := hex.EncodeToString(buf.Bytes())
	return txHex
}