Script

All bitcoin transactions have scripts embedded into its inputs and outputs. The scripts use a very simple programming language, which is evaluated from left to right using a stack. The language is designed such that it guarantees all scripts will execute in a limited amount of time (it is not Turing-Complete).

When a transaction is validated, the input scripts are concatenated with the output scripts and evaluated. To be valid, all transaction scripts must evaluate to true. A good analogy for how this works is that the output scripts are puzzles that specify in which conditions can those bitcoins be spent. The input scripts provide the correct data to make those output scripts evaluate to true.

For more detailed information about the bitcoin scripting language, check the online reference on bitcoin's wiki.

The Script object provides an interface to construct, parse, and identify bitcoin scripts. It also gives simple interfaces to create most common script types. This class is useful if you want to create custom input or output scripts. In other case, you should probably use Transaction.

Script creation

Here's how to use Script to create the five most common script types:

Pay to Public Key Hash (p2pkh)

This is the most commonly used transaction output script. It's used to pay to a bitcoin address (a bitcoin address is a public key hash encoded in base58check)

// create a new p2pkh paying to a specific address
var address = Address.fromString('1NaTVwXDDUJaXDQajoa9MqHhz4uTxtgK14');
var script = Script.buildPublicKeyHashOut(address);
assert(script.toString() === 'OP_DUP OP_HASH160 20 0xecae7d092947b7ee4998e254aa48900d26d2ce1d OP_EQUALVERIFY OP_CHECKSIG');

Pay to Public Key (p2pk)

Pay to public key scripts are a simplified form of the p2pkh, but aren't commonly used in new transactions anymore, because p2pkh scripts are more secure (the public key is not revealed until the output is spent).

// create a new p2pk paying to a specific public key
var pubkey = new PublicKey('022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da');
var script = Script.buildPublicKeyOut(pubkey);
assert(script.toString() === '33 0x022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da OP_CHECKSIG');

Pay to Multisig (p2ms)

Multisig outputs allow to share control of bitcoins between several keys. When creating the script, one specifies the public keys that control the funds, and how many of those keys are required to sign off spending transactions to be valid. An output with N public keys of which M are required is called an m-of-n output (For example, 2-of-3, 3-of-5, 4-of-4, etc.)

Note that regular multisig outputs are rarely used nowadays. The best practice is to use a p2sh multisig output (See Script#toScriptHashOut()).

// create a new 2-of-3 multisig output from 3 given public keys
var pubkeys = [
  new PublicKey('022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da'),
  new PublicKey('03e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e9'),
  new PublicKey('021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc18'),
];
var threshold = 2;
var script = Script.buildMultisigOut(pubkeys, threshold);
assert(script.toString() === 'OP_2 33 0x022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da'
      + ' 33 0x03e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e9'
      + ' 33 0x021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc18 OP_3 OP_CHECKMULTISIG');

Pay to Script Hash (p2sh)

Pay to script hash outputs are scripts that contain the hash of another script, called redeemScript. To spend bitcoins sent in a p2sh output, the spending transaction must provide a script matching the script hash and data which makes the script evaluate to true. This allows to defer revealing the spending conditions to the moment of spending. It also makes it possible for the receiver to set the conditions to spend those bitcoins.

Most multisig transactions today use p2sh outputs where the redeemScript is a multisig output.

// create a p2sh multisig output
var pubkeys = [
  new PublicKey('022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da'),
  new PublicKey('03e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e9'),
  new PublicKey('021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc18'),
];
var redeemScript = Script.buildMultisigOut(pubkeys, 2);
var script = redeemScript.toScriptHashOut();
assert(script.toString() === 'OP_HASH160 20 0x620a6eeaf538ec9eb89b6ae83f2ed8ef98566a03 OP_EQUAL');

Data output

Data outputs are used to push data into the blockchain. Up to 40 bytes can be pushed in a standard way, but more data can be used, if a miner decides to accept the transaction.

var data = 'hello world!!!';
var script = Script.buildDataOut(data);
assert(script.toString() === 'OP_RETURN 14 0x68656c6c6f20776f726c64212121'

Custom Scripts

To create a custom Script instance, you must rely on the lower-level methods add and prepend. Both methods accept the same parameter types, and insert an opcode or data at the beginning (prepend) or end (add) of the Script.

var script = Script()
  .add('OP_IF')                       // add an opcode by name
  .prepend(114)                       // add OP_2SWAP by code
  .add(Opcode.OP_NOT)                 // add an opcode object
  .add(new Buffer('bacacafe', 'hex')) // add a data buffer (will append the size of the push operation first)

assert(script.toString() === 'OP_2SWAP OP_IF OP_NOT 4 0xbacacafe');

Script Parsing and Identification

Script has an easy interface to parse raw scripts from the network or bitcoind, and to extract useful information. An illustrative example (for more options check the API reference)

var raw_script = new Buffer('5221022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da2103e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e921021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc1853ae', 'hex');
var s = new Script(raw_script);
console.log(s.toString());
// 'OP_2 33 0x022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da 33 0x03e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e9 33 0x021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc18 OP_3 OP_CHECKMULTISIG'

s.isPublicKeyHashOut() // false
s.isScriptHashOut() // false
s.isMultisigOut() // true

Script Interpreting and Validation

To validate a transaction, the bitcoin network validates all of its inputs and outputs. To validate an input, the input's script is concatenated with the referenced output script, and the result is executed. If at the end of execution the stack contains a 'true' value, then the transaction is valid. You can do this in bitcore by using the Interpreter class. The entry point (and probably the only interface you'll need for most applications) is the method Interpreter#verify().

You can use it like this:

var inputScript = Script('OP_1');
var outputScript = Script('OP_15 OP_ADD OP_16 OP_EQUAL');

var verified = Interpreter().verify(inputScript, outputScript);
// verified will be true

Note that verify expects two scripts: one is the input script (scriptSig) and the other is the output script (scriptPubkey). This is because different conditions are checked for each.

It also accepts some optional parameters, assuming defaults if not provided:

// first we create a transaction
var tx = new Transaction()
  .from(utxo)
  .to(toAddress, 100000)
  .sign(privateKey);

// we then extract the signature from the first input
var inputIndex = 0;
var signature = tx.getSignatures(privateKey)[inputIndex].signature;

var scriptSig = Script.buildPublicKeyHashIn(publicKey, signature);
var flags = Interpreter.SCRIPT_VERIFY_P2SH | Interpreter.SCRIPT_VERIFY_STRICTENC;
var verified = Interpreter().verify(scriptSig, scriptPubkey, tx, inputIndex, flags);

Interpreter()

Bitcoin transactions contain scripts. Each input has a script called the scriptSig, and each output has a script called the scriptPubkey. To validate an input, the input's script is concatenated with the referenced output script, and the result is executed. If at the end of execution the stack contains a "true" value, then the transaction is valid.

The primary way to use this class is via the verify function. e.g., Interpreter().verify( ... );

Kind: global function

interpreter.verify(scriptSig, scriptPubkey, [tx], nin, flags)

Verifies a Script by executing it and returns true if it is valid. This function needs to be provided with the scriptSig and the scriptPubkey separately.

Kind: instance method of Interpreter

Param Type Description
scriptSig Script the script's first part (corresponding to the tx input)
scriptPubkey Script the script's last part (corresponding to the tx output)
[tx] Transaction the Transaction containing the scriptSig in one input (used to check signature validity for some opcodes like OP_CHECKSIG)
nin number index of the transaction input containing the scriptSig verified.
flags number evaluation flags. See Interpreter.SCRIPT_* constants Translated from bitcoind's VerifyScript

interpreter.checkSignatureEncoding()

Translated from bitcoind's CheckSignatureEncoding

Kind: instance method of Interpreter

interpreter.checkPubkeyEncoding()

Translated from bitcoind's CheckPubKeyEncoding

Kind: instance method of Interpreter

interpreter.evaluate()

Based on bitcoind's EvalScript function, with the inner loop moved to Interpreter.prototype.step() bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104

Kind: instance method of Interpreter

interpreter.checkLockTime(nLockTime) ⇒ boolean

Checks a locktime parameter with the transaction's locktime. There are two times of nLockTime: lock-by-blockheight and lock-by-blocktime, distinguished by whether nLockTime < LOCKTIME_THRESHOLD = 500000000

See the corresponding code on bitcoin core: https://github.com/bitcoin/bitcoin/blob/ffd75adce01a78b3461b3ff05bcc2b530a9ce994/src/script/interpreter.cpp#L1129

Kind: instance method of Interpreter
Returns: boolean - true if the transaction's locktime is less than or equal to the transaction's locktime

Param Type Description
nLockTime BN the locktime read from the script

interpreter.step()

Based on the inner loop of bitcoind's EvalScript function bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104

Kind: instance method of Interpreter

Script

Kind: global class

new Script(from)

A bitcoin transaction script. Each transaction's inputs and outputs has a script that is evaluated to validate it's spending.

See https://en.bitcoin.it/wiki/Script

Param Type Description
from Object | string | Buffer optional data to populate script

script.isPublicKeyHashOut() ⇒ boolean

Kind: instance method of Script
Returns: boolean - if this is a pay to pubkey hash output script

script.isPublicKeyHashIn() ⇒ boolean

Kind: instance method of Script
Returns: boolean - if this is a pay to public key hash input script

script.isPublicKeyOut() ⇒ boolean

Kind: instance method of Script
Returns: boolean - if this is a public key output script

script.isPublicKeyIn() ⇒ boolean

Kind: instance method of Script
Returns: boolean - if this is a pay to public key input script

script.isScriptHashOut() ⇒ boolean

Kind: instance method of Script
Returns: boolean - if this is a p2sh output script

script.isScriptHashIn() ⇒ boolean

Kind: instance method of Script
Returns: boolean - if this is a p2sh input script Note that these are frequently indistinguishable from pubkeyhashin

script.isMultisigOut() ⇒ boolean

Kind: instance method of Script
Returns: boolean - if this is a mutlsig output script

script.isMultisigIn() ⇒ boolean

Kind: instance method of Script
Returns: boolean - if this is a multisig input script

script.isDataOut() ⇒ boolean

Kind: instance method of Script
Returns: boolean - true if this is a valid standard OP_RETURN output

script.getData() ⇒ Buffer

Retrieve the associated data for this script. In the case of a pay to public key hash or P2SH, return the hash. In the case of a standard OP_RETURN, return the data

Kind: instance method of Script

script.isPushOnly() ⇒ boolean

Kind: instance method of Script
Returns: boolean - if the script is only composed of data pushing opcodes or small int opcodes (OP_0, OP_1, ..., OP_16)

script.classify() ⇒ object

Kind: instance method of Script
Returns: object - The Script type if it is a known form, or Script.UNKNOWN if it isn't

script.classifyOutput() ⇒ object

Kind: instance method of Script
Returns: object - The Script type if it is a known form, or Script.UNKNOWN if it isn't

script.classifyInput() ⇒ object

Kind: instance method of Script
Returns: object - The Script type if it is a known form, or Script.UNKNOWN if it isn't

script.isStandard() ⇒ boolean

Kind: instance method of Script
Returns: boolean - if script is one of the known types

script.prepend(obj) ⇒ Script

Adds a script element at the start of the script.

Kind: instance method of Script
Returns: Script - this script instance

Param Type Description
obj * a string, number, Opcode, Buffer, or object to add

script.equals()

Compares a script with another script

Kind: instance method of Script

script.add(obj) ⇒ Script

Adds a script element to the end of the script.

Kind: instance method of Script
Returns: Script - this script instance

Param Type Description
obj * a string, number, Opcode, Buffer, or object to add

script.toScriptHashOut() ⇒ Script

Kind: instance method of Script
Returns: Script - a new pay to script hash script that pays to this script

script.getAddressInfo() ⇒ Address | boolean

Will return the associated address information object

Kind: instance method of Script

script.toAddress([network]) ⇒ Address | boolean

Kind: instance method of Script
Returns: Address | boolean - the associated address for this script if possible, or false

Param Type
[network] Network

script.findAndDelete()

Analogous to bitcoind's FindAndDelete. Find and delete equivalent chunks, typically used with push data chunks. Note that this will find and delete not just the same data, but the same data with the same push data op as produced by default. i.e., if a pushdata in a tx does not use the minimal pushdata op, then when you try to remove the data it is pushing, it will not be removed, because they do not use the same pushdata op.

Kind: instance method of Script

script.checkMinimalPush() ⇒ boolean

Comes from bitcoind's script interpreter CheckMinimalPush function

Kind: instance method of Script
Returns: boolean - if the chunk {i} is the smallest way to push that particular data.

script._decodeOP_N(opcode) ⇒ number

Comes from bitcoind's script DecodeOP_N function

Kind: instance method of Script
Returns: number - numeric value in range of 0 to 16

Param Type
opcode number

script.getSignatureOperationsCount(use) ⇒ number

Comes from bitcoind's script GetSigOpCount(boolean) function

Kind: instance method of Script
Returns: number - number of signature operations required by this script

Param Type Description
use boolean current (true) or pre-version-0.6 (false) logic

Script.buildMultisigOut(publicKeys, threshold, [opts]) ⇒ Script

Kind: static method of Script
Returns: Script - a new Multisig output script for given public keys, requiring m of those public keys to spend

Param Type Description
publicKeys Array.<PublicKey> list of all public keys controlling the output
threshold number amount of required signatures to spend the output
[opts] Object Several options: - noSorting: defaults to false, if true, don't sort the given public keys before creating the script

Script.buildMultisigIn(pubkeys, threshold, signatures, [opts]) ⇒ Script

A new Multisig input script for the given public keys, requiring m of those public keys to spend

Kind: static method of Script

Param Type Description
pubkeys Array.<PublicKey> list of all public keys controlling the output
threshold number amount of required signatures to spend the output
signatures Array and array of signature buffers to append to the script
[opts] Object
[opts.noSorting] boolean don't sort the given public keys before creating the script (false by default)
[opts.cachedMultisig] Script don't recalculate the redeemScript

Script.buildP2SHMultisigIn(pubkeys, threshold, signatures, [opts]) ⇒ Script

A new P2SH Multisig input script for the given public keys, requiring m of those public keys to spend

Kind: static method of Script

Param Type Description
pubkeys Array.<PublicKey> list of all public keys controlling the output
threshold number amount of required signatures to spend the output
signatures Array and array of signature buffers to append to the script
[opts] Object
[opts.noSorting] boolean don't sort the given public keys before creating the script (false by default)
[opts.cachedMultisig] Script don't recalculate the redeemScript

Script.buildPublicKeyHashOut(to) ⇒ Script

Kind: static method of Script
Returns: Script - a new pay to public key hash output for the given address or public key

Param Type Description
to Address | PublicKey destination address or public key

Script.buildPublicKeyOut() ⇒ Script

Kind: static method of Script
Returns: Script - a new pay to public key output for the given public key

Script.buildDataOut(data, encoding) ⇒ Script

Kind: static method of Script
Returns: Script - a new OP_RETURN script with data

Param Type Description
data string | Buffer the data to embed in the output
encoding string the type of encoding of the string

Script.buildScriptHashOut(script) ⇒ Script

Kind: static method of Script
Returns: Script - new pay to script hash script for given script

Param Type Description
script Script | Address the redeemScript for the new p2sh output. It can also be a p2sh address

Script.buildPublicKeyIn(signature, [sigtype])

Builds a scriptSig (a script for an input) that signs a public key output script.

Kind: static method of Script

Param Type Description
signature Signature | Buffer a Signature object, or the signature in DER canonical encoding
[sigtype] number the type of the signature (defaults to SIGHASH_ALL)

Script.buildPublicKeyHashIn(publicKey, signature, [sigtype])

Builds a scriptSig (a script for an input) that signs a public key hash output script.

Kind: static method of Script

Param Type Description
publicKey Buffer | string | PublicKey
signature Signature | Buffer a Signature object, or the signature in DER canonical encoding
[sigtype] number the type of the signature (defaults to SIGHASH_ALL)

Script.empty() ⇒ Script

Kind: static method of Script
Returns: Script - an empty script

Script.fromAddress() ⇒ Script

Kind: static method of Script
Returns: Script - an output script built from the address