package
4.1.1
Repository: https://github.com/decred/dcrd.git
Documentation: pkg.go.dev

# README

stdscript

Build Status ISC License Doc

Overview

This package provides facilities for identifying and extracting data from transaction scripts that are considered standard by the default policy of most nodes.

Understanding Standardness Versus Consensus

Under the hood, all regular transactions make use of transaction scripts with consensus-enforced semantics determined by an associated scripting language version in order to create smart contracts that impose constraints required to redeem funds.

The consensus rules consist of executing these transaction scripts in a virtual machine and further dictate that the result of the execution must evaluate to true. In particular, this means that scripts may be composed of any sequence of supported opcodes so long as they evaluate to true.

Recall that the full transaction script that is executed is the concatenation of two parts:

  1. The output script of a transaction (also known as the public key script)
  2. The input script of a transaction spending the aforementioned output (also known as the signature script)

Standard transaction scripts are public key scripts which are only composed of a well-defined sequence of opcodes that are widely used to achieve a specific goal such as requiring signatures to spend funds or anchoring data into the chain. In other words, standard scripts are a restricted subset of all possible public key scripts such that they conform to well-defined templates of a recognized form.

In addition, in order to improve overall efficiency of the network and limit potential denial of service attacks, the default policy of most nodes is to only accept and relay scripts which are considered standard, however, that in no way implies a transaction with non-standard scripts (any script that is not one of the recognized forms) is invalid per the consensus rules.

This distinction between standardness and consensus is extremely important for developers working on the consensus rules since what is considered a standard script can change at any time, while script execution for a given scripting language version must remain valid forever! To be explicit, the consensus rules must NOT reference or interact with code dealing with standard scripts directly in any way as that would lead to breaking perfectly valid scripts that may no longer be considered standard by policy.

This package is named stdscript to clearly convey that these scripts are particular recognized forms that most software considers standard by policy and therefore, as previously stated, must NOT be referenced by consensus code.

Pitfall with Special Script Types Enforced by Consensus

One important point of potential confusion to be cognizant of is that some of the script types, such as pay-to-script-hash, as well as all of the stake-related scripts, additionally have special consensus enforcement which means the consensus rules must also recognize them. In other words, they are both consensus scripts as well as recognized standard scripts.

This is particularly relevant to the Decred staking system since a distinguishing aspect of it is that its scripts are tightly controlled by consensus to only permit very specific scripts, unlike regular transactions which allow scripts composed of any sequence of opcodes that evaluate to true.

Consequently, it might be tempting to make use of the code in this package for identifying them for the purposes of enforcement since it is conveniently available, however, as previously stated, developers must NOT reference any code in this package from code that enforces consensus rules as this package will change with policy over time and therefore would lead to breaking the consensus rules.

Recognized Version 0 Standard Scripts

The following table lists the version 0 script types this package recognizes along with whether the type only applies to the staking system, and the type of the raw data that can be extracted:

Version 0 Script TypeStake?Data Type
p2pk-ecdsa-secp256k1N[]byte
p2pk-ed25519N[]byte
p2pk-schnorr-secp256k1N[]byte
p2pkh-ecdsa-secp256k1N[]byte
p2pkh-ed25519N[]byte
p2pkh-schnorr-secp256k1N[]byte
p2shN[]byte
ecdsa-multisigNMultiSigDetailsV0
nulldataN[]byte
stake submission p2pkhY[]byte
stake submission p2shY[]byte
stake generation p2pkhY[]byte
stake generation p2shY[]byte
stake revocation p2pkhY[]byte
stake revocation p2shY[]byte
stake change p2pkhY[]byte
stake change p2shY[]byte
treasury addY-
treasury generation p2pkhY[]byte
treasury generation p2shY[]byte

Abbreviations:

  • p2pk = Pay-to-public-key
  • p2pkh = Pay-to-public-key-hash
  • p2sh = Pay-to-script-hash

Package Usage Primer

Interacting with existing standard scripts typically falls into the following categories:

  • Analyzing them to determine their type
  • Extracting data

Determining Script Type

In order to provide a more ergonomic and efficient API depending on the specific needs of callers, this package offers three approaches to determining script types:

  1. Determining the script type as a ScriptType enum. For example, DetermineScriptType and DetermineScriptTypeV0.
  2. Determining if a script is a specific type directly. For example, IsPubKeyHashScript, IsPubKeyHashScriptV0, and IsScriptHashScript.
  3. Determining if a script is a specific type by checking if the relevant version-specific data was extracted. For example, ExtractPubKeyHashV0 and ExtractScriptHashV0.

The first approach is most suitable for callers that want to work with and display information about a wide variety of script types, such as block explorers.

The second approach is better suited to callers that are looking for a very specific script type as it is more efficient to check for a single type instead of checking all types to produce an enum as in the first approach.

The third approach is aimed more at callers that need access to the relevant data from the script in addition to merely determining the type. Unless noted otherwise in the documentation for a specific method, the data extraction methods only return data if the provided script is actually of the associated type. For example, when a wallet needs to determine if a transaction script is a pay-to-pubkey-hash script that involves a particular public key hash, instead of calling IsPubKeyHashScriptV0 (or worse calling DetermineScriptType and checking the returned enum type) followed by ExtractPubKeyHashV0, it is more efficient to simply call ExtractPubKeyHashV0 and check if the data returned is not nil followed by using said data.

It is also worth noting that the first two approaches offer API methods that accept the scripting language version as a parameter as well as their version-specific variants that make it clear from the API exactly which script types are supported for a given version at compile time. The third method, on the other hand, only offers version-specific methods. This is discussed further in the Extracting Data section.

Extracting Data

Callers that work with standard scripts often need to obtain the type and version-specific data. For example, a caller will likely need to be able to determine the number of required signatures and individual public keys from a version 0 ECDSA multisignature script for further processing.

This package provides several version-specific data extraction methods, such as ExtractPubKeyHashV0 and ExtractMultiSigScriptDetailsV0, for this purpose.

It should be noted that unlike the script type determination methods, this package does not offer version-agnostic variants of the data extraction methods that accept a dynamic version. This is a deliberate design choice that was made because the associated data is highly dependent on both the specific type of script and the scripting language version, so any version-agnostic methods would need to return interfaces that callers would have to type assert based on the version thereby defeating the original intention of using a version-agnostic method to begin with.

Provably Pruneable Scripts

A provably pruneable script is a public key script that is of a specific form that is provably unspendable and therefore is safe to prune from the set of unspent transaction outputs. They are primarily useful for anchoring commitments into the blockchain and are the preferred method to achieve that goal.

This package provides the version-specific ProvablyPruneableScriptV0 method for this purpose.

Note that no version-agnostic variant of the method that accepts a dynamic version is provided since the exact details of what is considered standard is likely to change between scripting language versions, so callers will necessarily have to ensure appropriate data is provided based on the version.

Additional Convenience Methods

As mentioned in the overview, standardness only applies to public key scripts. However, despite perhaps not fitting well with the name of the package, some additional convenience methods are provided for detecting and extracting data from common redeem scripts (the target script of a standard pay-to-script-hash script) as follows:

  • Version 0 ECDSA multisignature redeem scripts
  • Version 0 atomic swap redeem scripts

Installation and Updating

This package is part of the github.com/decred/dcrd/txscript/v4 module. Use the standard go tooling for working with modules to incorporate it.

Examples

  • DetermineScriptType

    Demonstrates determining the type of a script for a given scripting language version.

  • ExtractPubKeyHashV0

    Demonstrates extracting a public key hash from a standard pay-to-pubkey-hash script for scripting language version 0.

  • ExtractScriptHashV0

    Demonstrates extracting a script hash from a standard pay-to-script-hash script for scripting language version 0.

License

Package stdscript is licensed under the copyfree ISC License.

# Functions

DetermineRequiredSigs attempts to identify the number of signatures required by the passed script for the known standard types.
DetermineRequiredSigsV0 attempts to identify the number of signatures required by the passed version 0 script for the known standard types.
DetermineScriptType returns the type of the script passed.
DetermineScriptTypeV0 returns the type of the passed version 0 script for the known standard types.
ExtractAddrs analyzes the passed public key script and returns the associated script type along with any addresses associated with it when possible.
ExtractAddrsV0 analyzes the passed version 0 public key script and returns the associated script type along with any addresses associated with it when possible.
ExtractAtomicSwapDataPushesV0 returns the data pushes from an atomic swap contract using version 0 scripts if it is one.
ExtractCompressedPubKeyV0 extracts a compressed public key from the passed script if it is a standard version 0 pay-to-compressed-secp256k1-pubkey script.
ExtractMultiSigScriptDetailsV0 attempts to extract details from the passed version 0 script if it is a standard ECDSA multisig script.
ExtractPubKeyAltDetailsV0 extracts the public key and signature type from the passed script if it is a standard version 0 pay-to-alt-pubkey script.
ExtractPubKeyEd25519V0 extracts a public key from the passed script if it is a standard version 0 pay-to-ed25519-pubkey script.
ExtractPubKeyHashAltDetailsV0 extracts the public key hash and signature type from the passed script if it is a standard version 0 pay-to-alt-pubkey-hash script.
ExtractPubKeyHashEd25519V0 extracts the public key hash from the passed script if it is a standard version 0 pay-to-pubkey-hash-ed25519 script.
ExtractPubKeyHashSchnorrSecp256k1V0 extracts the public key hash from the passed script if it is a standard version 0 pay-to-pubkey-hash-schnorr-secp256k1 script.
ExtractPubKeyHashV0 extracts the public key hash from the passed script if it is a standard version 0 pay-to-pubkey-hash-ecdsa-secp256k1 script.
ExtractPubKeySchnorrSecp256k1V0 extracts a public key from the passed script if it is a standard version 0 pay-to-schnorr-secp256k1-pubkey script.
ExtractPubKeyV0 extracts either a compressed or uncompressed public key from the passed script if it is either a standard version 0 pay-to-compressed-secp256k1-pubkey or pay-to-uncompressed-secp256k1-pubkey script, respectively.
ExtractScriptHashV0 extracts the script hash from the passed script if it is a standard version 0 pay-to-script-hash script.
ExtractStakeChangePubKeyHashV0 extracts the public key hash from the passed script if it is a standard version 0 stake change pay-to-pubkey-hash script.
ExtractStakeChangeScriptHashV0 extracts the script hash from the passed script if it is a standard version 0 stake change pay-to-script-hash script.
ExtractStakeGenPubKeyHashV0 extracts the public key hash from the passed script if it is a standard version 0 stake generation pay-to-pubkey-hash script.
ExtractStakeGenScriptHashV0 extracts the script hash from the passed script if it is a standard version 0 stake generation pay-to-script-hash script.
ExtractStakePubKeyHashV0 extracts the public key hash from the passed script if it is any one of the supported standard version 0 stake-tagged pay-to-pubkey-hash scripts.
ExtractStakeRevocationPubKeyHashV0 extracts the public key hash from the passed script if it is a standard version 0 stake revocation pay-to-pubkey-hash script.
ExtractStakeRevocationScriptHashV0 extracts the script hash from the passed script if it is a standard version 0 stake revocation pay-to-script-hash script.
ExtractStakeScriptHashV0 extracts the script hash from the passed script if it is any one of the supported standard version 0 stake-tagged pay-to-script-hash scripts.
ExtractStakeSubmissionPubKeyHashV0 extracts the public key hash from the passed script if it is a standard version 0 stake submission pay-to-pubkey-hash script.
ExtractStakeSubmissionScriptHashV0 extracts the script hash from the passed script if it is a standard version 0 stake submission pay-to-script-hash script.
ExtractTreasuryGenPubKeyHashV0 extracts the public key hash from the passed script if it is a standard version 0 treasury generation pay-to-pubkey-hash script.
ExtractTreasuryGenScriptHashV0 extracts the script hash from the passed script if it is a standard version 0 treasury generation pay-to-script-hash script.
ExtractUncompressedPubKeyV0 extracts an uncompressed public key from the passed script if it is a standard version 0 pay-to-uncompressed-secp256k1-pubkey script.
IsMultiSigScript returns whether or not the passed script is a standard ECDSA multisig script.
IsMultiSigScriptV0 returns whether or not the passed script is a standard version 0 ECDSA multisig script.
IsMultiSigSigScript returns whether or not the passed script appears to be a signature script which consists of a pay-to-script-hash multi-signature redeem script.
IsMultiSigSigScriptV0 returns whether or not the passed script appears to be a version 0 signature script which consists of a pay-to-script-hash multi-signature redeem script.
IsNullDataScript returns whether or not the passed script is a standard null data script.
IsNullDataScriptV0 returns whether or not the passed script is a standard version 0 null data script.
IsPubKeyEd25519Script returns whether or not the passed script is a standard pay-to-ed25519-pubkey script.
IsPubKeyEd25519ScriptV0 returns whether or not the passed script is a standard version 0 pay-to-ed25519-pubkey script.
IsPubKeyHashEd25519Script returns whether or not the passed script is a standard pay-to-pubkey-hash-ed25519 script.
IsPubKeyHashEd25519ScriptV0 returns whether or not the passed script is a standard version 0 pay-to-pubkey-hash-ed25519 script.
IsPubKeyHashSchnorrSecp256k1Script returns whether or not the passed script is a standard pay-to-pubkey-hash-schnorr-secp256k1 script.
IsPubKeyHashSchnorrSecp256k1ScriptV0 returns whether or not the passed script is a standard version 0 pay-to-pubkey-hash-schnorr-secp256k1 script.
IsPubKeyHashScript returns whether or not the passed script is a standard pay-to-pubkey-hash-ecdsa-secp256k1 script.
IsPubKeyHashScriptV0 returns whether or not the passed script is a standard version 0 pay-to-pubkey-hash-ecdsa-secp256k1 script.
IsPubKeySchnorrSecp256k1Script returns whether or not the passed script is a standard pay-to-schnorr-secp256k1-pubkey script.
IsPubKeySchnorrSecp256k1ScriptV0 returns whether or not the passed script is a standard version 0 pay-to-schnorr-secp256k1-pubkey script.
IsPubKeyScript returns whether or not the passed script is either a standard pay-to-compressed-secp256k1-pubkey or pay-to-uncompressed-secp256k1-pubkey script.
IsPubKeyScriptV0 returns whether or not the passed script is either a standard version 0 pay-to-compressed-secp256k1-pubkey or pay-to-uncompressed-secp256k1-pubkey script.
IsScriptHashScript returns whether or not the passed script is a standard pay-to-script-hash script.
IsScriptHashScriptV0 returns whether or not the passed script is a standard version 0 pay-to-script-hash script.
IsStakeChangePubKeyHashScript returns whether or not the passed script is a standard stake change pay-to-pubkey-hash script.
IsStakeChangePubKeyHashScriptV0 returns whether or not the passed script is a standard version 0 stake change pay-to-pubkey-hash script.
IsStakeChangeScriptHashScript returns whether or not the passed script is a standard stake change pay-to-script-hash script.
IsStakeChangeScriptHashScriptV0 returns whether or not the passed script is a standard version 0 stake change pay-to-script-hash script.
IsStakeGenPubKeyHashScript returns whether or not the passed script is a standard stake generation pay-to-pubkey-hash script.
IsStakeGenPubKeyHashScriptV0 returns whether or not the passed script is a standard version 0 stake generation pay-to-pubkey-hash script.
IsStakeGenScriptHashScript returns whether or not the passed script is a standard stake generation pay-to-script-hash script.
IsStakeGenScriptHashScriptV0 returns whether or not the passed script is a standard version 0 stake generation pay-to-script-hash script.
IsStakeRevocationPubKeyHashScript returns whether or not the passed script is a standard stake revocation pay-to-pubkey-hash script.
IsStakeRevocationPubKeyHashScriptV0 returns whether or not the passed script is a standard version 0 stake revocation pay-to-pubkey-hash script.
IsStakeRevocationScriptHashScript returns whether or not the passed script is a standard stake revocation pay-to-script-hash script.
IsStakeRevocationScriptHashScriptV0 returns whether or not the passed script is a standard version 0 stake revocation pay-to-script-hash script.
IsStakeSubmissionPubKeyHashScript returns whether or not the passed script is a standard stake submission pay-to-pubkey-hash script.
IsStakeSubmissionPubKeyHashScriptV0 returns whether or not the passed script is a standard version 0 stake submission pay-to-pubkey-hash script.
IsStakeSubmissionScriptHashScript returns whether or not the passed script is a standard stake submission pay-to-script-hash script.
IsStakeSubmissionScriptHashScriptV0 returns whether or not the passed script is a standard version 0 stake submission pay-to-script-hash script.
IsStandardAltSignatureTypeV0 returns whether or not the provided version 0 script opcode represents a push of a standard alt signature type.
IsTreasuryAddScript returns whether or not the passed script is a supported treasury add script.
IsTreasuryAddScriptV0 returns whether or not the passed script is a supported version 0 treasury add script.
IsTreasuryGenPubKeyHashScript returns whether or not the passed script is a standard treasury generation pay-to-pubkey-hash script.
IsTreasuryGenPubKeyHashScriptV0 returns whether or not the passed script is a standard version 0 treasury generation pay-to-pubkey-hash script.
IsTreasuryGenScriptHashScript returns whether or not the passed script is a standard treasury generation pay-to-script-hash script.
IsTreasuryGenScriptHashScriptV0 returns whether or not the passed script is a standard version 0 treasury generation pay-to-script-hash script.
MultiSigRedeemScriptFromScriptSigV0 attempts to extract a multi-signature redeem script from a version 0 P2SH-redeeming input.
MultiSigScriptV0 returns a valid version 0 script for a multisignature redemption where the specified threshold number of the keys in the given public keys are required to have signed the transaction for success.
ProvablyPruneableScriptV0 returns a valid version 0 provably-pruneable script which consists of an OP_RETURN followed by the passed data.

# Constants

ErrNegativeRequiredSigs is returned from MultiSigScript when the specified number of required signatures is negative.
ErrPubKeyType is returned when a script contains invalid public keys.
ErrTooManyRequiredSigs is returned from MultiSigScript when the specified number of required signatures is larger than the number of provided public keys.
ErrTooMuchNullData is returned when attempting to generate a provably-pruneable script with data that exceeds the maximum allowed length.
ErrUnsupportedScriptVersion indicates that a given script version is not supported.
MaxDataCarrierSizeV0 is the maximum number of bytes allowed in pushed data to be considered a standard version 0 provably pruneable nulldata script.
STMultiSig identifies a standard script that imposes an encumbrance that requires a given number of valid ECDSA signatures which correspond to given secp256k1 public keys.
STNonStandard indicates a script is none of the recognized standard forms.
STNullData identifies a standard null data script that is provably prunable.
STPubKeyEcdsaSecp256k1 identifies a standard script that imposes an encumbrance that requires a valid ECDSA signature for a specific secp256k1 public key.
STPubKeyEd25519 identifies a standard script that imposes an encumbrance that requires a valid Ed25519 signature for a specific Ed25519 public key.
STPubKeyHashEcdsaSecp256k1 identifies a standard script that imposes an encumbrance that requires a secp256k1 public key that hashes to a specific value along with a valid ECDSA signature for that public key.
STPubKeyHashEd25519 identifies a standard script that imposes an encumbrance that requires an Ed25519 public key that hashes to a specific value along with a valid Ed25519 signature for that public key.
STPubKeyHashSchnorrSecp256k1 identifies a standard script that imposes an encumbrance that requires a secp256k1 public key that hashes to a specific value along with a valid EC-Schnorr-DCRv0 signature for that public key.
STPubKeySchnorrSecp256k1 identifies a standard script that imposes an encumbrance that requires a valid EC-Schnorr-DCRv0 signature for a specific secp256k1 public key.
STScriptHash identifies a standard script that imposes an encumbrance that requires a script that hashes to a specific value along with all of the encumbrances that script itself imposes.
STStakeChangePubKeyHash identifies a script that is only valid when used as part of supported transactions in the staking system.
STStakeChangeScriptHash identifies a script that is only valid when used as part of supported transactions in the staking system.
STStakeGenPubKeyHash identifies a script that is only valid when used as part of a vote transaction in the staking system.
STStakeGenScriptHash identifies a script that is only valid when used as part of a vote transaction in the staking system.
STStakeRevocationPubKeyHash identifies a script that is only valid when used as part of a revocation transaction in the staking system.
STStakeRevocationScriptHash identifies a script that is only valid when used as part of a revocation transaction in the staking system.
STStakeSubmissionPubKeyHash identifies a script that is only valid when used as part of a ticket purchase transaction in the staking system and is used for imposing voting rights.
STStakeSubmissionScriptHash identifies a script that is only valid when used as part of a ticket purchase transaction in the staking system and is used for imposing voting rights.
STTreasuryAdd identifies a script that is only valid when used as part supported transactions in the staking system and adds value to the treasury account.
STTreasuryGenPubKeyHash identifies a script that is only valid when used as part supported transactions in the staking system and generates utxos from the treasury account.
STTreasuryGenScriptHash identifies a script that is only valid when used as part supported transactions in the staking system and generates utxos from the treasury account.

# Structs

AtomicSwapDataPushesV0 houses the data pushes found in hash-based atomic swap contracts using version 0 scripts.
Error identifies an script-related error.
MultiSigDetailsV0 houses details extracted from a standard version 0 ECDSA multisig script.

# Type aliases

ErrorKind identifies a kind of error.
ScriptType identifies the type of known scripts in the blockchain that are typically considered standard by the default policy of most nodes.