diff --git a/docs/transaction.md b/docs/transaction.md index 0f17c8e..e8851b3 100644 --- a/docs/transaction.md +++ b/docs/transaction.md @@ -142,13 +142,27 @@ There are a series of methods used for serialization: * `toObject`: Returns a plain javascript object with no methods and enough information to fully restore the state of this transaction. Using other serialization methods (except for `toJSON`) will cause a some information to be lost. * `toJSON`: Returns a string with a JSON-encoded version of the output for `toObject`. * `toString` or `uncheckedSerialize`: Returns an hexadecimal serialization of the transaction, in the [serialization format for bitcoin](https://bitcoin.org/en/developer-reference#raw-transaction-format). -* `serialize`: Does a series of checks before serializing the transaction: - - Check that the fee to be used is not very small or very large - - Check for dust outputs +* `serialize`: Does a series of checks before serializing the transaction * `inspect`: Returns a string with some information about the transaction (currently a string formated as ``, that only shows the serialized value of the transaction. * `toBuffer`: Serializes the transaction for sending over the wire in the bitcoin network * `toBufferWriter`: Uses an already existing BufferWriter to copy over the serialized transaction +## Serialization Checks + +When serializing, the Bitcore library performs a series of checks. These can be disabled by providing an object to the `serialize` method with the checks that you'll like to skip. + +* `disableLargeFees` avoids checking that the fee is no more than `Transaction.FEE_PER_KB * Transaction.FEE_SECURITY_MARGIN * size_in_kb`. +* `disableSmallFees` avoids checking that the fee is less than `Transaction.FEE_PER_KB * size_in_kb / Transaction.FEE_SECURITY_MARGIN`. +* `disableIsFullySigned` does not check if all inputs are fully signed +* `disableDustOutputs` does not check for dust outputs being generated +* `disableMoreOutputThanInput` avoids checking that the sum of the output amounts is less than or equal to the sum of the amounts for the outputs being spent in the transaction + +These are the current default values in the Bitcore library involved on these checks: + +* `Transaction.FEE_PER_KB`: `10000` (satoshis per kilobyte) +* `Transaction.FEE_SECURITY_MARGIN`: `15` +* `Transaction.DUST_AMOUNT`: 5460 (satoshis) + ## Fee calculation When outputs' value don't sum up to the same amount that inputs, the difference in bitcoins goes to the miner of the block that includes this transaction. The concept of a "change address" usually is associated with this: an output with an address that can be spent by the creator of the transaction. diff --git a/lib/transaction/transaction.js b/lib/transaction/transaction.js index 22f4bfa..de7c4b8 100644 --- a/lib/transaction/transaction.js +++ b/lib/transaction/transaction.js @@ -24,10 +24,6 @@ var PrivateKey = require('../privatekey'); var Block = require('../block'); var BN = require('../crypto/bn'); -var CURRENT_VERSION = 1; -var DEFAULT_NLOCKTIME = 0; -var DEFAULT_SEQNUMBER = 0xFFFFFFFF; - /** * Represents a transaction, a set of inputs and outputs to change ownership of tokens * @@ -62,6 +58,16 @@ function Transaction(serialized) { } } +var CURRENT_VERSION = 1; +var DEFAULT_NLOCKTIME = 0; +var DEFAULT_SEQNUMBER = 0xFFFFFFFF; + +// Minimum amount for an output for it not to be considered a dust output +Transaction.DUST_AMOUNT = 5460; + +// Margin of error to allow fees in the vecinity of the expected value but doesn't allow a big difference +Transaction.FEE_SECURITY_MARGIN = 15; + // max amount of satoshis in circulation Transaction.MAX_MONEY = 21000000 * 1e8; @@ -71,6 +77,13 @@ Transaction.NLOCKTIME_BLOCKHEIGHT_LIMIT = 5e8; // Max value for an unsigned 32 bit value Transaction.NLOCKTIME_MAX_VALUE = 4294967295; +// Value used for fee estimation (satoshis per kilobyte) +Transaction.FEE_PER_KB = 10000; + +// Safe upper bound for change address script size in bytes +Transaction.CHANGE_OUTPUT_MAX_SIZE = 20 + 4 + 34 + 4; +Transaction.MAXIMUM_EXTRA_SIZE = 4 + 9 + 9 + 4; + /* Constructors and Serialization */ /** @@ -179,8 +192,6 @@ Transaction.prototype.getSerializationError = function(opts) { } }; -Transaction.FEE_SECURITY_MARGIN = 15; - Transaction.prototype._isFeeTooLarge = function() { var fee = this._getUnspentValue(); var maximumFee = Math.floor(Transaction.FEE_SECURITY_MARGIN * this._estimateFee()); @@ -201,8 +212,6 @@ Transaction.prototype._missingChange = function() { return !this._changeScript; }; -Transaction.DUST_AMOUNT = 5460; - Transaction.prototype._hasDustOutputs = function() { var index, output; for (index in this.outputs) { @@ -712,10 +721,6 @@ Transaction.prototype._clearSignatures = function() { }); }; -Transaction.FEE_PER_KB = 10000; -// Safe upper bound for change address script -Transaction.CHANGE_OUTPUT_MAX_SIZE = 20 + 4 + 34 + 4; - Transaction._estimateFee = function(size, amountAvailable) { var fee = Math.ceil(size / Transaction.FEE_PER_KB); if (amountAvailable > fee) { @@ -724,8 +729,6 @@ Transaction._estimateFee = function(size, amountAvailable) { return Math.ceil(size / 1000) * Transaction.FEE_PER_KB; }; -Transaction.MAXIMUM_EXTRA_SIZE = 4 + 9 + 9 + 4; - Transaction.prototype._estimateSize = function() { var result = Transaction.MAXIMUM_EXTRA_SIZE; _.each(this.inputs, function(input) {