@node-dlc/bitcoin
Version:
187 lines • 5.67 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Sequence = void 0;
const TimeLockMode_1 = require("./TimeLockMode");
const MAX_SEQUENCE = 4294967295;
const DEFAULT_SEQUENCE = 4294967295;
/**
* A transaction input's nSequence field according to BIP 68 where
* rules for relative timelocks are defined. Relative timelocks prevent
* mining of a transaction until a certain age of the spent output
* in blocks or timespan.
*
* nSequence defaults to a value of 0xffff_ffff which disables the field.
* When using a nLocktime, at least one transaction must be non-default.
* In this condition, it is standard to use 0xffff_fffe.
*/
class Sequence {
/**
* Parses the value from a byte stream
* @param reader
*/
static parse(reader) {
return new Sequence(reader.readUInt32LE());
}
/**
* Creates an nSequence value of 0xffff_fffe which is used to enable
* nLockTime.
*/
static locktime() {
return new Sequence(4294967294);
}
/**
* Creates an nSequence value of 0xffff_fffd which is used to
* enable opt-in full replace-by-fee.
*/
static rbf() {
return new Sequence(4294967293);
}
/**
* Creates an nSequence value of 0xffff_ffff
*/
static default() {
return new Sequence();
}
/**
* Creates an nSequence value of 0
*/
static zero() {
return new Sequence(0);
}
/**
* Creates an nSequence value with the specified block delay
* @param blocks number of blocks sequence must wait
*/
static blockDelay(blocks) {
const sut = new Sequence();
sut.blockDelay = blocks;
return sut;
}
/**
* Creates an nSequence value with the specified time delay
* @param seconds delay in seconds which will be rounded up to the
* nearest 512 second interval
*/
static timeDelay(seconds) {
const sut = new Sequence();
sut.timeDelay = seconds;
return sut;
}
/**
* Gets or sets the raw nSequence value.
*/
get value() {
return this._value;
}
set value(val) {
if (val < 0 || val > MAX_SEQUENCE)
throw new Error('Invalid nSequence');
this._value = val;
}
constructor(val = DEFAULT_SEQUENCE) {
this.value = val;
}
/**
* Returns true when the nSequence is the default value 0xffff_ffff
*/
get isDefault() {
return this.value === DEFAULT_SEQUENCE;
}
/**
* Returns true when the relative timelock is enabled. Technically
* this occurs when the top-most bit is unset. This means that the
* default value of 0xffff_ffff is unset.
*/
get enabled() {
return BigInt(this.value) >> BigInt(31) === BigInt(0);
}
/**
* Returns true for a value that would enable nLockTime. To enable
* nLockTime, at least one input in the transaction must have a
* non-default nSequence value.
*/
get isLockTimeSignaled() {
return this.value < DEFAULT_SEQUENCE;
}
/**
* Returns true for a value that would signal opt-in replace-by-fee
* as defined in BIP 125. To signal this, the nSequence must be less
* than 0xffffffff-1.
*/
get isRBFSignaled() {
return this.value < DEFAULT_SEQUENCE - 1;
}
/**
* Gets the time lock mode for the nSequence. Technically, the bit
* with index 22 controls the mode. When the bit is set, it will use
* time-based relative time locks. When it is unset, it will use
* block-based relatively time locks.
*/
get mode() {
if (this.value >> 22 === 1)
return TimeLockMode_1.TimeLockMode.Time;
else
return TimeLockMode_1.TimeLockMode.Block;
}
/**
* Gets or sets a relative timelock in seconds. Time-based relative
* time locks are encoded in 512 second granularity which is close
* to the 600 seconds each block should be generated in. When
* setting a value in seconds, it will rounded up to the nearest
* 512s granularity.
*/
get timeDelay() {
return (this.value & 0xffff) * 512;
}
set timeDelay(seconds) {
// calculate the delay in 512 second granularity
let value = Math.ceil(seconds / 512);
// if the value execeeds the max value, throw an error
if (value < 0 || value > 0xffff)
throw new Error('Invalid nSequence value');
// set the typeto time-based relatively timelock
value |= 1 << 22;
// set the actual value
this.value = value;
}
/**
* Gets or set a relative timelock in blocks.
*/
get blockDelay() {
return this.value & 0xffff;
}
set blockDelay(blocks) {
// if the value exceeds the max value, throw an error
if (blocks < 0 || blocks > 0xffff)
throw new Error('Invalid nSequence value');
this.value = blocks;
}
/**
* Serializes the value to a buffer
*/
serialize() {
const buf = Buffer.alloc(4);
buf.writeUInt32LE(this.value, 0);
return buf;
}
/**
* Returns the raw value as a hex encoded string, eg: 0xfffffffe
*/
toString() {
return '0x' + this.value.toString(16).padStart(8, '0');
}
/**
* Returns the raw value as a hex encoded string, eg: 0xfffffffe
*/
toJSON() {
return this.toString();
}
/**
* Clone via deep copy
*/
clone() {
return new Sequence(this._value);
}
}
exports.Sequence = Sequence;
//# sourceMappingURL=Sequence.js.map