txscript

package module
v4.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 14, 2024 License: ISC Imports: 22 Imported by: 70

README

txscript

Build Status ISC License Doc

Package txscript implements the Decred transaction script language. There is a comprehensive test suite.

This package has intentionally been designed so it can be used as a standalone package for any projects needing to use or validate Decred transaction scripts.

Decred Scripts

Decred provides a stack-based, FORTH-like language for the scripts in the Decred transactions. This language is not Turing complete although it is still fairly powerful.

Installation and Updating

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

Examples

  • Counting Opcodes in Scripts Demonstrates creating a script tokenizer instance and using it to count the number of opcodes a script contains.

License

Package txscript is licensed under the copyfree ISC License.

Documentation

Overview

Package txscript implements the Decred transaction script language.

This package provides data structures and functions to parse and execute decred transaction scripts.

Script Overview

Decred transaction scripts are written in a stack-base, FORTH-like language.

The Decred script language consists of a number of opcodes which fall into several categories such pushing and popping data to and from the stack, performing basic and bitwise arithmetic, conditional branching, comparing hashes, and checking cryptographic signatures. Scripts are processed from left to right and intentionally do not provide loops.

The vast majority of Decred scripts at the time of this writing are of several standard forms which consist of a spender providing a public key and a signature which proves the spender owns the associated private key. This information is used to prove the spender is authorized to perform the transaction.

One benefit of using a scripting language is added flexibility in specifying what conditions must be met in order to spend decred.

Errors

The errors returned by this package are of type txscript.ErrorKind wrapped by txscript.Error which has full support for the standard library errors.Is and errors.As functions. This allows the caller to programmatically determine the specific error while still providing rich error messages with contextual information. See the constants defined with ErrorKind in the package documentation for a full list.

Index

Examples

Constants

View Source
const (
	// MaxStackSize is the maximum combined height of stack and alt stack
	// during execution.
	MaxStackSize = 1024

	// MaxScriptSize is the maximum allowed length of a raw script.
	MaxScriptSize = 16384
)
View Source
const (

	// ErrInvalidIndex is returned when an out-of-bounds index is passed to
	// a function.
	ErrInvalidIndex = ErrorKind("ErrInvalidIndex")

	// ErrInvalidSigHashSingleIndex is returned when an attempt is
	// made to sign an input with the SigHashSingle hash type and an
	// index that is greater than or equal to the number of outputs.
	ErrInvalidSigHashSingleIndex = ErrorKind("ErrInvalidSigHashSingleIndex")

	// ErrUnsupportedScriptVersion is returned when an unsupported script
	// version is passed to a function which deals with script analysis.
	ErrUnsupportedScriptVersion = ErrorKind("ErrUnsupportedScriptVersion")

	// ErrEarlyReturn is returned when OP_RETURN is executed in the script.
	ErrEarlyReturn = ErrorKind("ErrEarlyReturn")

	// ErrEmptyStack is returned when the script evaluated without error,
	// but terminated with an empty top stack element.
	ErrEmptyStack = ErrorKind("ErrEmptyStack")

	// ErrEvalFalse is returned when the script evaluated without error but
	// terminated with a false top stack element.
	ErrEvalFalse = ErrorKind("ErrEvalFalse")

	// ErrScriptUnfinished is returned when CheckErrorCondition is called on
	// a script that has not finished executing.
	ErrScriptUnfinished = ErrorKind("ErrScriptUnfinished")

	// ErrScriptDone is returned when an attempt to execute an opcode is
	// made once all of them have already been executed.  This can happen
	// due to things such as a second call to Execute or calling Step after
	// all opcodes have already been executed.
	ErrInvalidProgramCounter = ErrorKind("ErrInvalidProgramCounter")

	// ErrScriptTooBig is returned if a script is larger than MaxScriptSize.
	ErrScriptTooBig = ErrorKind("ErrScriptTooBig")

	// ErrElementTooBig is returned if the size of an element to be pushed
	// to the stack is over MaxScriptElementSize.
	ErrElementTooBig = ErrorKind("ErrElementTooBig")

	// ErrTooManyOperations is returned if a script has more than
	// MaxOpsPerScript opcodes that do not push data.
	ErrTooManyOperations = ErrorKind("ErrTooManyOperations")

	// ErrStackOverflow is returned when stack and altstack combined depth
	// is over the limit.
	ErrStackOverflow = ErrorKind("ErrStackOverflow")

	// ErrInvalidPubKeyCount is returned when the number of public keys
	// specified for a multsig is either negative or greater than
	// MaxPubKeysPerMultiSig.
	ErrInvalidPubKeyCount = ErrorKind("ErrInvalidPubKeyCount")

	// ErrInvalidSignatureCount is returned when the number of signatures
	// specified for a multisig is either negative or greater than the
	// number of public keys.
	ErrInvalidSignatureCount = ErrorKind("ErrInvalidSignatureCount")

	// ErrNumOutOfRange is returned when the argument for an opcode that
	// expects numeric input is larger than the expected maximum number of
	// bytes.  For the most part, opcodes that deal with stack manipulation
	// via offsets, arithmetic, numeric comparison, and boolean logic are
	// those that this applies to.  However, any opcode that expects numeric
	// input may fail with this error.
	ErrNumOutOfRange = ErrorKind("ErrNumOutOfRange")

	// ErrVerify is returned when OP_VERIFY is encountered in a script and
	// the top item on the data stack does not evaluate to true.
	ErrVerify = ErrorKind("ErrVerify")

	// ErrEqualVerify is returned when OP_EQUALVERIFY is encountered in a
	// script and the top item on the data stack does not evaluate to true.
	ErrEqualVerify = ErrorKind("ErrEqualVerify")

	// ErrNumEqualVerify is returned when OP_NUMEQUALVERIFY is encountered
	// in a script and the top item on the data stack does not evaluate to
	// true.
	ErrNumEqualVerify = ErrorKind("ErrNumEqualVerify")

	// ErrCheckSigVerify is returned when OP_CHECKSIGVERIFY is encountered
	// in a script and the top item on the data stack does not evaluate to
	// true.
	ErrCheckSigVerify = ErrorKind("ErrCheckSigVerify")

	// ErrCheckSigVerify is returned when OP_CHECKMULTISIGVERIFY is
	// encountered in a script and the top item on the data stack does not
	// evaluate to true.
	ErrCheckMultiSigVerify = ErrorKind("ErrCheckMultiSigVerify")

	// ErrCheckSigAltVerify is returned when OP_CHECKSIGALTVERIFY is
	// encountered in a script and the top item on the data stack does not
	// evaluate to true.
	ErrCheckSigAltVerify = ErrorKind("ErrCheckSigAltVerify")

	// ErrP2SHStakeOpCodes is returned when one or more stake opcodes are
	// found in the redeem script of a pay-to-script-hash script.
	ErrP2SHStakeOpCodes = ErrorKind("ErrP2SHStakeOpCodes")

	// ErrDisabledOpcode is returned when a disabled opcode is encountered
	// in a script.
	ErrDisabledOpcode = ErrorKind("ErrDisabledOpcode")

	// ErrReservedOpcode is returned when an opcode marked as reserved
	// is encountered in a script.
	ErrReservedOpcode = ErrorKind("ErrReservedOpcode")

	// ErrMalformedPush is returned when a data push opcode tries to push
	// more bytes than are left in the script.
	ErrMalformedPush = ErrorKind("ErrMalformedPush")

	// ErrInvalidStackOperation is returned when a stack operation is
	// attempted with a number that is invalid for the current stack size.
	ErrInvalidStackOperation = ErrorKind("ErrInvalidStackOperation")

	// ErrUnbalancedConditional is returned when an OP_ELSE or OP_ENDIF is
	// encountered in a script without first having an OP_IF or OP_NOTIF or
	// the end of script is reached without encountering an OP_ENDIF when
	// an OP_IF or OP_NOTIF was previously encountered.
	ErrUnbalancedConditional = ErrorKind("ErrUnbalancedConditional")

	// ErrNegativeSubstrIdx is returned when an OP_SUBSTR, OP_LEFT, or
	// OP_RIGHT opcode encounters a negative index.
	ErrNegativeSubstrIdx = ErrorKind("ErrNegativeSubstrIdx")

	// ErrOverflowSubstrIdx is returned when an OP_SUBSTR, OP_LEFT, or
	// OP_RIGHT opcode encounters an index that is larger than the max
	// allowed index that can operate on the string or the start index
	// is greater than the end index for OP_SUBSTR.
	ErrOverflowSubstrIdx = ErrorKind("ErrOverflowSubstrIdx")

	// ErrNegativeRotation is returned when an OP_ROTL or OP_ROTR attempts
	// to perform a rotation with a negative rotation count.
	ErrNegativeRotation = ErrorKind("ErrNegativeRotation")

	// ErrOverflowRotation is returned when an OP_ROTL or OP_ROTR opcode
	// encounters a rotation count that is larger than the maximum allowed
	// value for a uint32 bit rotation.
	ErrOverflowRotation = ErrorKind("ErrOverflowRotation")

	// ErrDivideByZero is returned when an OP_DIV of OP_MOD attempts to
	// divide by zero.
	ErrDivideByZero = ErrorKind("ErrDivideByZero")

	// ErrNegativeRotation is returned when an OP_LSHIFT or OP_RSHIFT opcode
	// attempts to perform a shift with a negative count.
	ErrNegativeShift = ErrorKind("ErrNegativeShift")

	// ErrOverflowShift is returned when an OP_LSHIFT or OP_RSHIFT opcode
	// encounters a shift count that is larger than the maximum allowed value
	// for a shift.
	ErrOverflowShift = ErrorKind("ErrOverflowShift")

	// ErrP2SHTreasuryOpCodes is returned when one or more treasury opcodes
	// are found in the redeem script of a pay-to-script-hash script.
	ErrP2SHTreasuryOpCodes = ErrorKind("ErrP2SHTreasuryOpCodes")

	// ErrMinimalData is returned when the script contains push operations
	// that do not use the minimal opcode required.
	ErrMinimalData = ErrorKind("ErrMinimalData")

	// ErrInvalidSigHashType is returned when a signature hash type is not
	// one of the supported types.
	ErrInvalidSigHashType = ErrorKind("ErrInvalidSigHashType")

	// ErrSigTooShort is returned when a signature that should be a
	// canonically-encoded DER signature is too short.
	ErrSigTooShort = ErrorKind("ErrSigTooShort")

	// ErrSigTooLong is returned when a signature that should be a
	// canonically-encoded DER signature is too long.
	ErrSigTooLong = ErrorKind("ErrSigTooLong")

	// ErrSigInvalidSeqID is returned when a signature that should be a
	// canonically-encoded DER signature does not have the expected ASN.1
	// sequence ID.
	ErrSigInvalidSeqID = ErrorKind("ErrSigInvalidSeqID")

	// ErrSigInvalidDataLen is returned when a signature that should be a
	// canonically-encoded DER signature does not specify the correct number
	// of remaining bytes for the R and S portions.
	ErrSigInvalidDataLen = ErrorKind("ErrSigInvalidDataLen")

	// ErrSigMissingSTypeID is returned when a signature that should be a
	// canonically-encoded DER signature does not provide the ASN.1 type ID
	// for S.
	ErrSigMissingSTypeID = ErrorKind("ErrSigMissingSTypeID")

	// ErrSigMissingSLen is returned when a signature that should be a
	// canonically-encoded DER signature does not provide the length of S.
	ErrSigMissingSLen = ErrorKind("ErrSigMissingSLen")

	// ErrSigInvalidSLen is returned when a signature that should be a
	// canonically-encoded DER signature does not specify the correct number
	// of bytes for the S portion.
	ErrSigInvalidSLen = ErrorKind("ErrSigInvalidSLen")

	// ErrSigInvalidRIntID is returned when a signature that should be a
	// canonically-encoded DER signature does not have the expected ASN.1
	// integer ID for R.
	ErrSigInvalidRIntID = ErrorKind("ErrSigInvalidRIntID")

	// ErrSigZeroRLen is returned when a signature that should be a
	// canonically-encoded DER signature has an R length of zero.
	ErrSigZeroRLen = ErrorKind("ErrSigZeroRLen")

	// ErrSigNegativeR is returned when a signature that should be a
	// canonically-encoded DER signature has a negative value for R.
	ErrSigNegativeR = ErrorKind("ErrSigNegativeR")

	// ErrSigTooMuchRPadding is returned when a signature that should be a
	// canonically-encoded DER signature has too much padding for R.
	ErrSigTooMuchRPadding = ErrorKind("ErrSigTooMuchRPadding")

	// ErrSigInvalidSIntID is returned when a signature that should be a
	// canonically-encoded DER signature does not have the expected ASN.1
	// integer ID for S.
	ErrSigInvalidSIntID = ErrorKind("ErrSigInvalidSIntID")

	// ErrSigZeroSLen is returned when a signature that should be a
	// canonically-encoded DER signature has an S length of zero.
	ErrSigZeroSLen = ErrorKind("ErrSigZeroSLen")

	// ErrSigNegativeS is returned when a signature that should be a
	// canonically-encoded DER signature has a negative value for S.
	ErrSigNegativeS = ErrorKind("ErrSigNegativeS")

	// ErrSigTooMuchSPadding is returned when a signature that should be a
	// canonically-encoded DER signature has too much padding for S.
	ErrSigTooMuchSPadding = ErrorKind("ErrSigTooMuchSPadding")

	// ErrSigHighS is returned when a signature that should be a
	// canonically-encoded DER signature has an S value that is higher than
	// the curve half order.
	ErrSigHighS = ErrorKind("ErrSigHighS")

	// ErrNotPushOnly is returned when a script that is required to only
	// push data to the stack performs other operations.  A couple of cases
	// where this applies is for a pay-to-script-hash signature script when
	// bip16 is active and when the ScriptVerifySigPushOnly flag is set.
	ErrNotPushOnly = ErrorKind("ErrNotPushOnly")

	// ErrPubKeyType is returned when the script contains invalid public keys.
	ErrPubKeyType = ErrorKind("ErrPubKeyType")

	// ErrCleanStack is returned when the ScriptVerifyCleanStack flag
	// is set, and after evaluation, the stack does not contain only a
	// single element.
	ErrCleanStack = ErrorKind("ErrCleanStack")

	// ErrDiscourageUpgradableNOPs is returned when the
	// ScriptDiscourageUpgradableNops flag is set and a NOP opcode is
	// encountered in a script.
	ErrDiscourageUpgradableNOPs = ErrorKind("ErrDiscourageUpgradableNOPs")

	// ErrNegativeLockTime is returned when a script contains an opcode that
	// interprets a negative lock time.
	ErrNegativeLockTime = ErrorKind("ErrNegativeLockTime")

	// ErrUnsatisfiedLockTime is returned when a script contains an opcode
	// that involves a lock time and the required lock time has not been
	// reached.
	ErrUnsatisfiedLockTime = ErrorKind("ErrUnsatisfiedLockTime")
)

These constants are used to identify a specific ErrorKind.

View Source
const (
	OP_0                   = 0x00 // 0
	OP_FALSE               = 0x00 // 0 - AKA OP_0
	OP_DATA_1              = 0x01 // 1
	OP_DATA_2              = 0x02 // 2
	OP_DATA_3              = 0x03 // 3
	OP_DATA_4              = 0x04 // 4
	OP_DATA_5              = 0x05 // 5
	OP_DATA_6              = 0x06 // 6
	OP_DATA_7              = 0x07 // 7
	OP_DATA_8              = 0x08 // 8
	OP_DATA_9              = 0x09 // 9
	OP_DATA_10             = 0x0a // 10
	OP_DATA_11             = 0x0b // 11
	OP_DATA_12             = 0x0c // 12
	OP_DATA_13             = 0x0d // 13
	OP_DATA_14             = 0x0e // 14
	OP_DATA_15             = 0x0f // 15
	OP_DATA_16             = 0x10 // 16
	OP_DATA_17             = 0x11 // 17
	OP_DATA_18             = 0x12 // 18
	OP_DATA_19             = 0x13 // 19
	OP_DATA_20             = 0x14 // 20
	OP_DATA_21             = 0x15 // 21
	OP_DATA_22             = 0x16 // 22
	OP_DATA_23             = 0x17 // 23
	OP_DATA_24             = 0x18 // 24
	OP_DATA_25             = 0x19 // 25
	OP_DATA_26             = 0x1a // 26
	OP_DATA_27             = 0x1b // 27
	OP_DATA_28             = 0x1c // 28
	OP_DATA_29             = 0x1d // 29
	OP_DATA_30             = 0x1e // 30
	OP_DATA_31             = 0x1f // 31
	OP_DATA_32             = 0x20 // 32
	OP_DATA_33             = 0x21 // 33
	OP_DATA_34             = 0x22 // 34
	OP_DATA_35             = 0x23 // 35
	OP_DATA_36             = 0x24 // 36
	OP_DATA_37             = 0x25 // 37
	OP_DATA_38             = 0x26 // 38
	OP_DATA_39             = 0x27 // 39
	OP_DATA_40             = 0x28 // 40
	OP_DATA_41             = 0x29 // 41
	OP_DATA_42             = 0x2a // 42
	OP_DATA_43             = 0x2b // 43
	OP_DATA_44             = 0x2c // 44
	OP_DATA_45             = 0x2d // 45
	OP_DATA_46             = 0x2e // 46
	OP_DATA_47             = 0x2f // 47
	OP_DATA_48             = 0x30 // 48
	OP_DATA_49             = 0x31 // 49
	OP_DATA_50             = 0x32 // 50
	OP_DATA_51             = 0x33 // 51
	OP_DATA_52             = 0x34 // 52
	OP_DATA_53             = 0x35 // 53
	OP_DATA_54             = 0x36 // 54
	OP_DATA_55             = 0x37 // 55
	OP_DATA_56             = 0x38 // 56
	OP_DATA_57             = 0x39 // 57
	OP_DATA_58             = 0x3a // 58
	OP_DATA_59             = 0x3b // 59
	OP_DATA_60             = 0x3c // 60
	OP_DATA_61             = 0x3d // 61
	OP_DATA_62             = 0x3e // 62
	OP_DATA_63             = 0x3f // 63
	OP_DATA_64             = 0x40 // 64
	OP_DATA_65             = 0x41 // 65
	OP_DATA_66             = 0x42 // 66
	OP_DATA_67             = 0x43 // 67
	OP_DATA_68             = 0x44 // 68
	OP_DATA_69             = 0x45 // 69
	OP_DATA_70             = 0x46 // 70
	OP_DATA_71             = 0x47 // 71
	OP_DATA_72             = 0x48 // 72
	OP_DATA_73             = 0x49 // 73
	OP_DATA_74             = 0x4a // 74
	OP_DATA_75             = 0x4b // 75
	OP_PUSHDATA1           = 0x4c // 76
	OP_PUSHDATA2           = 0x4d // 77
	OP_PUSHDATA4           = 0x4e // 78
	OP_1NEGATE             = 0x4f // 79
	OP_RESERVED            = 0x50 // 80
	OP_1                   = 0x51 // 81 - AKA OP_TRUE
	OP_TRUE                = 0x51 // 81
	OP_2                   = 0x52 // 82
	OP_3                   = 0x53 // 83
	OP_4                   = 0x54 // 84
	OP_5                   = 0x55 // 85
	OP_6                   = 0x56 // 86
	OP_7                   = 0x57 // 87
	OP_8                   = 0x58 // 88
	OP_9                   = 0x59 // 89
	OP_10                  = 0x5a // 90
	OP_11                  = 0x5b // 91
	OP_12                  = 0x5c // 92
	OP_13                  = 0x5d // 93
	OP_14                  = 0x5e // 94
	OP_15                  = 0x5f // 95
	OP_16                  = 0x60 // 96
	OP_NOP                 = 0x61 // 97
	OP_VER                 = 0x62 // 98
	OP_IF                  = 0x63 // 99
	OP_NOTIF               = 0x64 // 100
	OP_VERIF               = 0x65 // 101
	OP_VERNOTIF            = 0x66 // 102
	OP_ELSE                = 0x67 // 103
	OP_ENDIF               = 0x68 // 104
	OP_VERIFY              = 0x69 // 105
	OP_RETURN              = 0x6a // 106
	OP_TOALTSTACK          = 0x6b // 107
	OP_FROMALTSTACK        = 0x6c // 108
	OP_2DROP               = 0x6d // 109
	OP_2DUP                = 0x6e // 110
	OP_3DUP                = 0x6f // 111
	OP_2OVER               = 0x70 // 112
	OP_2ROT                = 0x71 // 113
	OP_2SWAP               = 0x72 // 114
	OP_IFDUP               = 0x73 // 115
	OP_DEPTH               = 0x74 // 116
	OP_DROP                = 0x75 // 117
	OP_DUP                 = 0x76 // 118
	OP_NIP                 = 0x77 // 119
	OP_OVER                = 0x78 // 120
	OP_PICK                = 0x79 // 121
	OP_ROLL                = 0x7a // 122
	OP_ROT                 = 0x7b // 123
	OP_SWAP                = 0x7c // 124
	OP_TUCK                = 0x7d // 125
	OP_CAT                 = 0x7e // 126
	OP_SUBSTR              = 0x7f // 127
	OP_LEFT                = 0x80 // 128
	OP_RIGHT               = 0x81 // 129
	OP_SIZE                = 0x82 // 130
	OP_INVERT              = 0x83 // 131
	OP_AND                 = 0x84 // 132
	OP_OR                  = 0x85 // 133
	OP_XOR                 = 0x86 // 134
	OP_EQUAL               = 0x87 // 135
	OP_EQUALVERIFY         = 0x88 // 136
	OP_ROTR                = 0x89 // 137
	OP_ROTL                = 0x8a // 138
	OP_1ADD                = 0x8b // 139
	OP_1SUB                = 0x8c // 140
	OP_2MUL                = 0x8d // 141
	OP_2DIV                = 0x8e // 142
	OP_NEGATE              = 0x8f // 143
	OP_ABS                 = 0x90 // 144
	OP_NOT                 = 0x91 // 145
	OP_0NOTEQUAL           = 0x92 // 146
	OP_ADD                 = 0x93 // 147
	OP_SUB                 = 0x94 // 148
	OP_MUL                 = 0x95 // 149
	OP_DIV                 = 0x96 // 150
	OP_MOD                 = 0x97 // 151
	OP_LSHIFT              = 0x98 // 152
	OP_RSHIFT              = 0x99 // 153
	OP_BOOLAND             = 0x9a // 154
	OP_BOOLOR              = 0x9b // 155
	OP_NUMEQUAL            = 0x9c // 156
	OP_NUMEQUALVERIFY      = 0x9d // 157
	OP_NUMNOTEQUAL         = 0x9e // 158
	OP_LESSTHAN            = 0x9f // 159
	OP_GREATERTHAN         = 0xa0 // 160
	OP_LESSTHANOREQUAL     = 0xa1 // 161
	OP_GREATERTHANOREQUAL  = 0xa2 // 162
	OP_MIN                 = 0xa3 // 163
	OP_MAX                 = 0xa4 // 164
	OP_WITHIN              = 0xa5 // 165
	OP_RIPEMD160           = 0xa6 // 166
	OP_SHA1                = 0xa7 // 167
	OP_BLAKE256            = 0xa8 // 168
	OP_HASH160             = 0xa9 // 169
	OP_HASH256             = 0xaa // 170
	OP_CODESEPARATOR       = 0xab // 171
	OP_CHECKSIG            = 0xac // 172
	OP_CHECKSIGVERIFY      = 0xad // 173
	OP_CHECKMULTISIG       = 0xae // 174
	OP_CHECKMULTISIGVERIFY = 0xaf // 175
	OP_NOP1                = 0xb0 // 176
	OP_NOP2                = 0xb1 // 177
	OP_CHECKLOCKTIMEVERIFY = 0xb1 // 177 - AKA OP_NOP2
	OP_NOP3                = 0xb2 // 178
	OP_CHECKSEQUENCEVERIFY = 0xb2 // 178 - AKA OP_NOP3
	OP_NOP4                = 0xb3 // 179
	OP_NOP5                = 0xb4 // 180
	OP_NOP6                = 0xb5 // 181
	OP_NOP7                = 0xb6 // 182
	OP_NOP8                = 0xb7 // 183
	OP_NOP9                = 0xb8 // 184
	OP_NOP10               = 0xb9 // 185
	OP_SSTX                = 0xba // 186 DECRED
	OP_SSGEN               = 0xbb // 187 DECRED
	OP_SSRTX               = 0xbc // 188 DECRED
	OP_SSTXCHANGE          = 0xbd // 189 DECRED
	OP_CHECKSIGALT         = 0xbe // 190 DECRED
	OP_CHECKSIGALTVERIFY   = 0xbf // 191 DECRED
	OP_SHA256              = 0xc0 // 192
	OP_TADD                = 0xc1 // 193 DECRED
	OP_TSPEND              = 0xc2 // 194 DECRED
	OP_TGEN                = 0xc3 // 195 DECRED
	OP_UNKNOWN196          = 0xc4 // 196
	OP_UNKNOWN197          = 0xc5 // 197
	OP_UNKNOWN198          = 0xc6 // 198
	OP_UNKNOWN199          = 0xc7 // 199
	OP_UNKNOWN200          = 0xc8 // 200
	OP_UNKNOWN201          = 0xc9 // 201
	OP_UNKNOWN202          = 0xca // 202
	OP_UNKNOWN203          = 0xcb // 203
	OP_UNKNOWN204          = 0xcc // 204
	OP_UNKNOWN205          = 0xcd // 205
	OP_UNKNOWN206          = 0xce // 206
	OP_UNKNOWN207          = 0xcf // 207
	OP_UNKNOWN208          = 0xd0 // 208
	OP_UNKNOWN209          = 0xd1 // 209
	OP_UNKNOWN210          = 0xd2 // 210
	OP_UNKNOWN211          = 0xd3 // 211
	OP_UNKNOWN212          = 0xd4 // 212
	OP_UNKNOWN213          = 0xd5 // 213
	OP_UNKNOWN214          = 0xd6 // 214
	OP_UNKNOWN215          = 0xd7 // 215
	OP_UNKNOWN216          = 0xd8 // 216
	OP_UNKNOWN217          = 0xd9 // 217
	OP_UNKNOWN218          = 0xda // 218
	OP_UNKNOWN219          = 0xdb // 219
	OP_UNKNOWN220          = 0xdc // 220
	OP_UNKNOWN221          = 0xdd // 221
	OP_UNKNOWN222          = 0xde // 222
	OP_UNKNOWN223          = 0xdf // 223
	OP_UNKNOWN224          = 0xe0 // 224
	OP_UNKNOWN225          = 0xe1 // 225
	OP_UNKNOWN226          = 0xe2 // 226
	OP_UNKNOWN227          = 0xe3 // 227
	OP_UNKNOWN228          = 0xe4 // 228
	OP_UNKNOWN229          = 0xe5 // 229
	OP_UNKNOWN230          = 0xe6 // 230
	OP_UNKNOWN231          = 0xe7 // 231
	OP_UNKNOWN232          = 0xe8 // 232
	OP_UNKNOWN233          = 0xe9 // 233
	OP_UNKNOWN234          = 0xea // 234
	OP_UNKNOWN235          = 0xeb // 235
	OP_UNKNOWN236          = 0xec // 236
	OP_UNKNOWN237          = 0xed // 237
	OP_UNKNOWN238          = 0xee // 238
	OP_UNKNOWN239          = 0xef // 239
	OP_UNKNOWN240          = 0xf0 // 240
	OP_UNKNOWN241          = 0xf1 // 241
	OP_UNKNOWN242          = 0xf2 // 242
	OP_UNKNOWN243          = 0xf3 // 243
	OP_UNKNOWN244          = 0xf4 // 244
	OP_UNKNOWN245          = 0xf5 // 245
	OP_UNKNOWN246          = 0xf6 // 246
	OP_UNKNOWN247          = 0xf7 // 247
	OP_UNKNOWN248          = 0xf8 // 248
	OP_INVALID249          = 0xf9 // 249 - bitcoin core internal
	OP_SMALLINTEGER        = 0xfa // 250 - bitcoin core internal
	OP_PUBKEYS             = 0xfb // 251 - bitcoin core internal
	OP_UNKNOWN252          = 0xfc // 252
	OP_PUBKEYHASH          = 0xfd // 253 - bitcoin core internal
	OP_PUBKEY              = 0xfe // 254 - bitcoin core internal
	OP_INVALIDOPCODE       = 0xff // 255 - bitcoin core internal
)

These constants are the values of the official opcodes used on the btc wiki, in bitcoin core and in most if not all other references and software related to handling DCR scripts.

View Source
const (
	MaxOpsPerScript       = 255  // Max number of non-push operations.
	MaxPubKeysPerMultiSig = 20   // Multisig can't have more sigs than this.
	MaxScriptElementSize  = 2048 // Max bytes pushable to the stack.
)

These are the constants specified for maximums in individual scripts.

View Source
const (

	// MathOpCodeMaxScriptNumLen is the maximum number of bytes data being
	// interpreted as an integer may be for the majority of op codes.
	MathOpCodeMaxScriptNumLen = 4

	// CltvMaxScriptNumLen is the maximum number of bytes data being interpreted
	// as an integer may be for by-time and by-height locks as interpreted by
	// CHECKLOCKTIMEVERIFY.
	//
	// The value comes from the fact that the current transaction locktime
	// is a uint32 resulting in a maximum locktime of 2^32-1 (the year
	// 2106).  However, script numbers are signed and therefore a standard
	// 4-byte ScriptNum would only support up to a maximum of 2^31-1 (the
	// year 2038).  Thus, a 5-byte ScriptNum is needed since it will support
	// up to 2^39-1 which allows dates beyond the current locktime limit.
	CltvMaxScriptNumLen = 5

	// CsvMaxScriptNumLen is the maximum number of bytes data being interpreted
	// as an integer may be for by-time and by-height locks as interpreted by
	// CHECKSEQUENCEVERIFY.
	//
	// The value comes from the fact that the current transaction sequence
	// is a uint32 resulting in a maximum sequence of 2^32-1.  However,
	// ScriptNums are signed and therefore a standard 4-byte ScriptNum would
	// only support up to a maximum of 2^31-1.  Thus, a 5-byte ScriptNum is
	// needed since it will support up to 2^39-1 which allows sequences
	// beyond the current sequence limit.
	CsvMaxScriptNumLen = 5
)
View Source
const (
	// SigHashSerializePrefix indicates the serialization does not include
	// any witness data.
	SigHashSerializePrefix = 1

	// SigHashSerializeWitness indicates the serialization only contains
	// witness data.
	SigHashSerializeWitness = 3
)
View Source
const (
	// LockTimeThreshold is the number below which a lock time is
	// interpreted to be a block number.  Since an average of one block
	// is generated per 10 minutes, this allows blocks for about 9,512
	// years.
	LockTimeThreshold = 5e8 // Tue Nov 5 00:53:20 1985 UTC
)
View Source
const ProactiveEvictionDepth = 2

ProactiveEvictionDepth is the depth of the block at which the signatures for the transactions within the block are nearly guaranteed to no longer be useful.

Variables

View Source
var OpcodeByName = make(map[string]byte)

OpcodeByName is a map that can be used to lookup an opcode by its human-readable name (OP_CHECKMULTISIG, OP_CHECKSIG, etc).

Functions

func AsSmallInt

func AsSmallInt(op byte) int

AsSmallInt returns the passed opcode, which MUST be true according to the IsSmallInt function, as an integer.

NOTE: This function is only valid for version 0 opcodes. Since the function does not accept a script version, the results are undefined for other script versions.

func CalcSignatureHash

func CalcSignatureHash(script []byte, hashType SigHashType, tx *wire.MsgTx, idx int, cachedPrefix *chainhash.Hash) ([]byte, error)

CalcSignatureHash computes the signature hash for the specified input of the target transaction observing the desired signature hash type. The cached prefix parameter allows the caller to optimize the calculation by providing the prefix hash to be reused in the case of SigHashAll without the SigHashAnyOneCanPay flag set.

NOTE: This function is only valid for version 0 scripts. Since the function does not accept a script version, the results are undefined for other script versions.

func CanonicalDataSize

func CanonicalDataSize(data []byte) int

CanonicalDataSize returns the number of bytes the canonical encoding of the data will take.

func CheckHashTypeEncoding

func CheckHashTypeEncoding(hashType SigHashType) error

CheckHashTypeEncoding returns whether or not the passed hashtype adheres to the strict encoding requirements.

func CheckPubKeyEncoding

func CheckPubKeyEncoding(pubKey []byte) error

CheckPubKeyEncoding returns an error if the passed public key does not adhere to the strict encoding requirements.

func CheckSignatureEncoding

func CheckSignatureEncoding(sig []byte) error

CheckSignatureEncoding returns whether or not the passed signature adheres to the strict encoding requirements.

func ContainsStakeOpCodes

func ContainsStakeOpCodes(pkScript []byte, isTreasuryEnabled bool) (bool, error)

ContainsStakeOpCodes returns whether or not a public key script contains any stake tagging opcodes.

NOTE: This function is only valid for version 0 scripts. Since the function does not accept a script version, the results are undefined for other script versions.

func DisasmString

func DisasmString(script []byte) (string, error)

DisasmString formats a disassembled script for one line printing. When the script fails to parse, the returned string will contain the disassembled script up to the point the failure occurred along with the string '[error]' appended. In addition, the reason the script failed to parse is returned if the caller wants more information about the failure.

NOTE: This function is only valid for version 0 scripts. Since the function does not accept a script version, the results are undefined for other script versions.

func ExtractScriptHash

func ExtractScriptHash(script []byte) []byte

ExtractScriptHash extracts the script hash from the passed script if it is a standard pay-to-script-hash script. It will return nil otherwise.

NOTE: This function is only valid for version 0 opcodes. Since the function does not accept a script version, the results are undefined for other script versions.

func GenerateSSGenBlockRef

func GenerateSSGenBlockRef(blockHash chainhash.Hash, height uint32) ([]byte, error)

GenerateSSGenBlockRef generates a block reference script for the given block hash and height which a block votes on. The script is for use in stake vote transactions.

func GenerateSSGenVotes

func GenerateSSGenVotes(votebits uint16) ([]byte, error)

GenerateSSGenVotes generates a vote script for the given vote bits. The script is for use in stake vote transactions.

func GetPreciseSigOpCount

func GetPreciseSigOpCount(scriptSig, scriptPubKey []byte, isTreasuryEnabled bool) int

GetPreciseSigOpCount returns the number of signature operations in scriptPubKey. If bip16 is true then scriptSig may be searched for the Pay-To-Script-Hash script in order to find the precise number of signature operations in the transaction. If the script fails to parse, then the count up to the point of failure is returned.

WARNING: This function always treats the passed script as version 0. Great care must be taken if introducing a new script version because it is used in consensus which, unfortunately as of the time of this writing, does not check script versions before counting their signature operations which means nodes on existing rules will count new version scripts as if they were version 0.

func GetSigOpCount

func GetSigOpCount(script []byte, isTreasuryEnabled bool) int

GetSigOpCount provides a quick count of the number of signature operations in a script. a CHECKSIG operations counts for 1, and a CHECK_MULTISIG for 20. If the script fails to parse, then the count up to the point of failure is returned.

WARNING: This function always treats the passed script as version 0. Great care must be taken if introducing a new script version because it is used in consensus which, unfortunately as of the time of this writing, does not check script versions before counting their signature operations which means nodes on existing rules will count new version scripts as if they were version 0.

func IsDERSigError

func IsDERSigError(err error) bool

IsDERSigError returns whether or not the provided error is one of the error kinds which are caused due to encountering a signature that is not a canonically-encoded DER signature.

func IsPayToScriptHash

func IsPayToScriptHash(script []byte) bool

IsPayToScriptHash returns true if the script is in the standard pay-to-script-hash (P2SH) format, false otherwise.

WARNING: This function always treats the passed script as version 0. Great care must be taken if introducing a new script version because it is used in consensus which, unfortunately as of the time of this writing, does not check script versions before determining if the script is a P2SH which means nodes on existing rules will analyze new version scripts as if they were version 0.

func IsPushOnlyScript

func IsPushOnlyScript(script []byte) bool

IsPushOnlyScript returns whether or not the passed script only pushes data according to the consensus definition of pushing data.

WARNING: This function always treats the passed script as version 0. Great care must be taken if introducing a new script version because it is used in consensus which, unfortunately as of the time of this writing, does not check script versions before checking if it is a push only script which means nodes on existing rules will treat new version scripts as if they were version 0.

func IsSmallInt

func IsSmallInt(op byte) bool

IsSmallInt returns whether or not the opcode is considered a small integer, which is an OP_0, or OP_1 through OP_16.

NOTE: This function is only valid for version 0 opcodes. Since the function does not accept a script version, the results are undefined for other script versions.

func IsStrictCompressedPubKeyEncoding

func IsStrictCompressedPubKeyEncoding(pubKey []byte) bool

IsStrictCompressedPubKeyEncoding returns whether or not the passed public key adheres to the strict compressed encoding requirements.

func IsStrictNullData

func IsStrictNullData(scriptVersion uint16, script []byte, requiredLen uint32) bool

IsStrictNullData returns whether or not the passed data is an OP_RETURN followed by specified length data push. It explicitly verifies that the opcode is identical to the required length. This function will always return false for required lengths > 75 bytes.

func IsStrictSignatureEncoding

func IsStrictSignatureEncoding(signature []byte) bool

IsStrictSignatureEncoding returns false if the passed signature does not adhere to the strict encoding requirements.

func IsUnspendable

func IsUnspendable(amount int64, pkScript []byte) bool

IsUnspendable returns whether the passed public key script is unspendable, or guaranteed to fail at execution. This allows inputs to be pruned instantly when entering the UTXO set. In Decred, all zero value outputs are unspendable.

NOTE: This function is only valid for version 0 scripts. Since the function does not accept a script version, the results are undefined for other script versions.

func UseLogger

func UseLogger(logger slog.Logger)

UseLogger uses a specified Logger to output package logging info.

Types

type Engine

type Engine struct {
	// contains filtered or unexported fields
}

Engine is the virtual machine that executes scripts.

func NewEngine

func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags, scriptVersion uint16, sigCache *SigCache) (*Engine, error)

NewEngine returns a new script engine for the provided public key script, transaction, and input index. The flags modify the behavior of the script engine according to the description provided by each flag.

func (*Engine) CheckErrorCondition

func (vm *Engine) CheckErrorCondition(finalScript bool) error

CheckErrorCondition returns nil if the running script has ended and was successful, leaving a true boolean on the stack. An error otherwise, including if the script has not finished.

func (*Engine) DisasmPC

func (vm *Engine) DisasmPC() (string, error)

DisasmPC returns the string for the disassembly of the opcode that will be next to execute when Step is called.

func (*Engine) DisasmScript

func (vm *Engine) DisasmScript(idx int) (string, error)

DisasmScript returns the disassembly string for the script at the requested offset index. Index 0 is the signature script and 1 is the public key script. In the case of pay-to-script-hash, index 2 is the redeem script once the execution has progressed far enough to have successfully verified script hash and thus add the script to the scripts to execute.

func (*Engine) Execute

func (vm *Engine) Execute() (err error)

Execute will execute all scripts in the script engine and return either nil for successful validation or an error if one occurred.

func (*Engine) GetAltStack

func (vm *Engine) GetAltStack() [][]byte

GetAltStack returns the contents of the alternate stack as an array where the last item in the array is the top of the stack.

func (*Engine) GetStack

func (vm *Engine) GetStack() [][]byte

GetStack returns the contents of the primary stack as an array. where the last item in the array is the top of the stack.

func (*Engine) SetAltStack

func (vm *Engine) SetAltStack(data [][]byte)

SetAltStack sets the contents of the alternate stack to the contents of the provided array where the last item in the array will be the top of the stack.

func (*Engine) SetStack

func (vm *Engine) SetStack(data [][]byte)

SetStack sets the contents of the primary stack to the contents of the provided array where the last item in the array will be the top of the stack.

func (*Engine) Step

func (vm *Engine) Step() (done bool, err error)

Step executes the next instruction and moves the program counter to the next opcode in the script, or the next script if the current has ended. Step will return true in the case that the last opcode was successfully executed.

The result of calling Step or any other method is undefined if an error is returned.

type ErrScriptNotCanonical

type ErrScriptNotCanonical string

ErrScriptNotCanonical identifies a non-canonical script. The caller can use a type assertion to detect this error type.

func (ErrScriptNotCanonical) Error

func (e ErrScriptNotCanonical) Error() string

Error implements the error interface.

type Error

type Error struct {
	Err         error
	Description string
}

Error identifies a script-related error. It is used to indicate three classes of errors:

  1. Script execution failures due to violating one of the many requirements imposed by the script engine or evaluating to false
  2. Improper API usage by callers
  3. Internal consistency check failures

It has full support for errors.Is and errors.As, so the caller can ascertain the specific reason for the error by checking the underlying error.

func (Error) Error

func (e Error) Error() string

Error satisfies the error interface and prints human-readable errors.

func (Error) Unwrap

func (e Error) Unwrap() error

Unwrap returns the underlying wrapped error.

type ErrorKind

type ErrorKind string

ErrorKind identifies a kind of script error.

func (ErrorKind) Error

func (e ErrorKind) Error() string

Error satisfies the error interface and prints human-readable errors.

type ScriptBuilder

type ScriptBuilder struct {
	// contains filtered or unexported fields
}

ScriptBuilder provides a facility for building custom scripts. It allows you to push opcodes, ints, and data while respecting canonical encoding. In general it does not ensure the script will execute correctly, however any data pushes which would exceed the maximum allowed script engine limits and are therefore guaranteed not to execute will not be pushed and will result in the Script function returning an error.

For example, the following would build a 2-of-3 multisig script for usage in a pay-to-script-hash (although in this situation stdscript.MultiSigScript() would be a better choice to generate the script):

builder := txscript.NewScriptBuilder()
builder.AddOp(txscript.OP_2).AddData(pubKey1).AddData(pubKey2)
builder.AddData(pubKey3).AddOp(txscript.OP_3)
builder.AddOp(txscript.OP_CHECKMULTISIG)
script, err := builder.Script()
if err != nil {
	// Handle the error.
	return
}
fmt.Printf("Final multi-sig script: %x\n", script)

func NewScriptBuilder

func NewScriptBuilder() *ScriptBuilder

NewScriptBuilder returns a new instance of a script builder. See ScriptBuilder for details.

func (*ScriptBuilder) AddData

func (b *ScriptBuilder) AddData(data []byte) *ScriptBuilder

AddData pushes the passed data to the end of the script. It automatically chooses canonical opcodes depending on the length of the data. A zero length buffer will lead to a push of empty data onto the stack (OP_0) and any push of data greater than MaxScriptElementSize will not modify the script since that is not allowed by the script engine. Also, the script will not be modified if pushing the data would cause the script to exceed the maximum allowed script engine size.

func (*ScriptBuilder) AddDataUnchecked

func (b *ScriptBuilder) AddDataUnchecked(data []byte) *ScriptBuilder

AddDataUnchecked should not typically be used by ordinary users as it does not include the checks which prevent data pushes larger than the maximum allowed sizes which leads to scripts that can't be executed. This is provided for testing purposes such as regression tests where sizes are intentionally made larger than allowed.

Use AddData instead.

func (*ScriptBuilder) AddInt64

func (b *ScriptBuilder) AddInt64(val int64) *ScriptBuilder

AddInt64 pushes the passed integer to the end of the script. The script will not be modified if pushing the data would cause the script to exceed the maximum allowed script engine size.

func (*ScriptBuilder) AddOp

func (b *ScriptBuilder) AddOp(opcode byte) *ScriptBuilder

AddOp pushes the passed opcode to the end of the script. The script will not be modified if pushing the opcode would cause the script to exceed the maximum allowed script engine size.

func (*ScriptBuilder) AddOps

func (b *ScriptBuilder) AddOps(opcodes []byte) *ScriptBuilder

AddOps pushes the passed opcodes to the end of the script. The script will not be modified if pushing the opcodes would cause the script to exceed the maximum allowed script engine size.

func (*ScriptBuilder) AddOpsUnchecked

func (b *ScriptBuilder) AddOpsUnchecked(opcodes []byte) *ScriptBuilder

AddOpsUnchecked should not typically be used by ordinary users as it does not include the checks which prevent scripts from exceeding the largest allowed script size which leads to scripts that can't be executed. This is provided for testing purposes such as regression tests where sizes are intentionally made larger than allowed.

Use AddOps instead.

func (*ScriptBuilder) Reset

func (b *ScriptBuilder) Reset() *ScriptBuilder

Reset resets the script so it has no content.

func (*ScriptBuilder) Script

func (b *ScriptBuilder) Script() ([]byte, error)

Script returns the currently built script. When any errors occurred while building the script, the script will be returned up the point of the first error along with the error.

type ScriptFlags

type ScriptFlags uint32

ScriptFlags is a bitmask defining additional operations or tests that will be done when executing a script pair.

const (
	// ScriptDiscourageUpgradableNops defines whether to verify that
	// currently unused opcodes in the NOP and UNKNOWN families are reserved
	// for future upgrades.  This flag must not be used for consensus
	// critical code nor applied to blocks as this flag is only for stricter
	// standard transaction checks.  This flag is only applied when the
	// above opcodes are executed.
	ScriptDiscourageUpgradableNops ScriptFlags = 1 << iota

	// ScriptVerifyCheckLockTimeVerify defines whether to verify that
	// a transaction output is spendable based on the locktime.
	// This is BIP0065.
	ScriptVerifyCheckLockTimeVerify

	// ScriptVerifyCheckSequenceVerify defines whether to allow execution
	// pathways of a script to be restricted based on the age of the output
	// being spent.  This is BIP0112.
	ScriptVerifyCheckSequenceVerify

	// ScriptVerifyCleanStack defines that the stack must contain only
	// one stack element after evaluation and that the element must be
	// true if interpreted as a boolean.  This is rule 6 of BIP0062.
	// This flag should never be used without the ScriptBip16 flag.
	ScriptVerifyCleanStack

	// ScriptVerifySigPushOnly defines that signature scripts must contain
	// only pushed data.  This is rule 2 of BIP0062.
	ScriptVerifySigPushOnly

	// ScriptVerifySHA256 defines whether to treat opcode 192 (previously
	// OP_UNKNOWN192) as the OP_SHA256 opcode which consumes the top item of
	// the data stack and replaces it with the sha256 of it.
	ScriptVerifySHA256

	// ScriptVerifyTreasury defines whether to treat opcode 193 (previously
	// OP_UNKNOWN193), opcode 194 (previously OP_UNKNOWN194) and opcode 195
	// (previously OP_UNKNOWN195) as the OP_TADD, OP_TSPEND and OP_TGEN
	// opcodes which add and spend an amount from the treasury.
	ScriptVerifyTreasury
)

type ScriptNum

type ScriptNum int64

ScriptNum represents a numeric value used in the scripting engine with special handling to deal with the subtle semantics required by consensus.

All numbers are stored on the data and alternate stacks encoded as little endian with a sign bit. All numeric opcodes such as OP_ADD, OP_SUB, and OP_MUL, are only allowed to operate on 4-byte integers in the range [-2^31 + 1, 2^31 - 1], however the results of numeric operations may overflow and remain valid so long as they are not used as inputs to other numeric operations or otherwise interpreted as an integer.

For example, it is possible for OP_ADD to have 2^31 - 1 for its two operands resulting 2^32 - 2, which overflows, but is still pushed to the stack as the result of the addition. That value can then be used as input to OP_VERIFY which will succeed because the data is being interpreted as a boolean. However, if that same value were to be used as input to another numeric opcode, such as OP_SUB, it must fail.

This type handles the aforementioned requirements by storing all numeric operation results as an int64 to handle overflow and provides the Bytes method to get the serialized representation (including values that overflow).

Then, whenever data is interpreted as an integer, it is converted to this type by using the MakeScriptNum function which will return an error if the number is out of range or not minimally encoded depending on parameters. Since all numeric opcodes involve pulling data from the stack and interpreting it as an integer, it provides the required behavior.

func MakeScriptNum

func MakeScriptNum(v []byte, scriptNumLen int) (ScriptNum, error)

MakeScriptNum interprets the passed serialized bytes as an encoded integer and returns the result as a script number.

Since the consensus rules dictate that serialized bytes interpreted as ints are only allowed to be in the range determined by a maximum number of bytes, on a per opcode basis, an error will be returned when the provided bytes would result in a number outside of that range. In particular, the range for the vast majority of opcodes dealing with numeric values are limited to 4 bytes and therefore will pass that value to this function resulting in an allowed range of [-2^31 + 1, 2^31 - 1].

An error will be returned if the encoding is not represented with the smallest possible number of bytes or is the negative 0 encoding, [0x80]. For example, consider the number 127. It could be encoded as [0x7f], [0x7f 0x00], [0x7f 0x00 0x00 ...], etc. All forms except [0x7f] will return an error.

The scriptNumLen is the maximum number of bytes the encoded value can be before an ErrNumOutOfRange is returned. This effectively limits the range of allowed values.

WARNING: Great care should be taken if passing a value larger than defaultScriptNumLen, which could lead to addition and multiplication overflows.

See the Bytes function documentation for example encodings.

func (ScriptNum) Bytes

func (n ScriptNum) Bytes() []byte

Bytes returns the number serialized as a little endian with a sign bit.

Example encodings:

   127 -> [0x7f]
  -127 -> [0xff]
   128 -> [0x80 0x00]
  -128 -> [0x80 0x80]
   129 -> [0x81 0x00]
  -129 -> [0x81 0x80]
   256 -> [0x00 0x01]
  -256 -> [0x00 0x81]
 32767 -> [0xff 0x7f]
-32767 -> [0xff 0xff]
 32768 -> [0x00 0x80 0x00]
-32768 -> [0x00 0x80 0x80]

func (ScriptNum) Int32

func (n ScriptNum) Int32() int32

Int32 returns the script number clamped to a valid int32. That is to say when the script number is higher than the max allowed int32, the max int32 value is returned and vice versa for the minimum value. Note that this behavior is different from a simple int32 cast because that truncates and the consensus rules dictate numbers which are directly cast to ints provide this behavior.

In practice, for most opcodes, the number should never be out of range since it will have been created with MakeScriptNum using the defaultScriptLen value, which rejects them. In case something in the future ends up calling this function against the result of some arithmetic, which IS allowed to be out of range before being reinterpreted as an integer, this will provide the correct behavior.

type ScriptTokenizer

type ScriptTokenizer struct {
	// contains filtered or unexported fields
}

ScriptTokenizer provides a facility for easily and efficiently tokenizing transaction scripts without creating allocations. Each successive opcode is parsed with the Next function, which returns false when iteration is complete, either due to successfully tokenizing the entire script or encountering a parse error. In the case of failure, the Err function may be used to obtain the specific parse error.

Upon successfully parsing an opcode, the opcode and data associated with it may be obtained via the Opcode and Data functions, respectively.

The ByteIndex function may be used to obtain the tokenizer's current offset into the raw script.

Example

This example demonstrates creating a script tokenizer instance and using it to count the number of opcodes a script contains.

// Create a script to use in the example.  Ordinarily this would come from
// some other source.
hash160 := stdaddr.Hash160([]byte("example"))
script, err := txscript.NewScriptBuilder().AddOp(txscript.OP_DUP).
	AddOp(txscript.OP_HASH160).AddData(hash160).
	AddOp(txscript.OP_EQUALVERIFY).AddOp(txscript.OP_CHECKSIG).Script()
if err != nil {
	fmt.Printf("failed to build script: %v\n", err)
	return
}

// Create a tokenizer to iterate the script and count the number of opcodes.
const scriptVersion = 0
var numOpcodes int
tokenizer := txscript.MakeScriptTokenizer(scriptVersion, script)
for tokenizer.Next() {
	numOpcodes++
}
if tokenizer.Err() != nil {
	fmt.Printf("script failed to parse: %v\n", err)
} else {
	fmt.Printf("script contains %d opcode(s)\n", numOpcodes)
}
Output:

script contains 5 opcode(s)

func MakeScriptTokenizer

func MakeScriptTokenizer(scriptVersion uint16, script []byte) ScriptTokenizer

MakeScriptTokenizer returns a new instance of a script tokenizer. Passing an unsupported script version will result in the returned tokenizer immediately having an err set accordingly.

See the docs for ScriptTokenizer for more details.

func (*ScriptTokenizer) ByteIndex

func (t *ScriptTokenizer) ByteIndex() int32

ByteIndex returns the current offset into the full script that will be parsed next and therefore also implies everything before it has already been parsed.

func (*ScriptTokenizer) Data

func (t *ScriptTokenizer) Data() []byte

Data returns the data associated with the most recently successfully parsed opcode.

func (*ScriptTokenizer) Done

func (t *ScriptTokenizer) Done() bool

Done returns true when either all opcodes have been exhausted or a parse failure was encountered and therefore the state has an associated error.

func (*ScriptTokenizer) Err

func (t *ScriptTokenizer) Err() error

Err returns any errors currently associated with the tokenizer. This will only be non-nil in the case a parsing error was encountered.

func (*ScriptTokenizer) Next

func (t *ScriptTokenizer) Next() bool

Next attempts to parse the next opcode and returns whether or not it was successful. It will not be successful if invoked when already at the end of the script, a parse failure is encountered, or an associated error already exists due to a previous parse failure.

In the case of a true return, the parsed opcode and data can be obtained with the associated functions and the offset into the script will either point to the next opcode or the end of the script if the final opcode was parsed.

In the case of a false return, the parsed opcode and data will be the last successfully parsed values (if any) and the offset into the script will either point to the failing opcode or the end of the script if the function was invoked when already at the end of the script.

Invoking this function when already at the end of the script is not considered an error and will simply return false.

func (*ScriptTokenizer) Opcode

func (t *ScriptTokenizer) Opcode() byte

Opcode returns the current opcode associated with the tokenizer.

func (*ScriptTokenizer) Script

func (t *ScriptTokenizer) Script() []byte

Script returns the full script associated with the tokenizer.

type SigCache

type SigCache struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

SigCache implements an ECDSA signature verification cache with a randomized entry eviction policy. Only valid signatures will be added to the cache. The benefits of SigCache are two fold. Firstly, usage of SigCache mitigates a DoS attack wherein an attack causes a victim's client to hang due to worst-case behavior triggered while processing attacker crafted invalid transactions. A detailed description of the mitigated DoS attack can be found here: https://bitslog.wordpress.com/2013/01/23/fixed-bitcoin-vulnerability-explanation-why-the-signature-cache-is-a-dos-protection/. Secondly, usage of the SigCache introduces a signature verification optimization which speeds up the validation of transactions within a block, if they've already been seen and verified within the mempool.

func NewSigCache

func NewSigCache(maxEntries uint) (*SigCache, error)

NewSigCache creates and initializes a new instance of SigCache. Its sole parameter 'maxEntries' represents the maximum number of entries allowed to exist in the SigCache at any particular moment. Random entries are evicted to make room for new entries that would cause the number of entries in the cache to exceed the max.

func (*SigCache) Add

func (s *SigCache) Add(sigHash chainhash.Hash, sig *ecdsa.Signature, pubKey *secp256k1.PublicKey, tx *wire.MsgTx)

Add adds an entry for a signature over 'sigHash' under public key 'pubKey' to the signature cache. In the event that the SigCache is 'full', an existing entry is randomly chosen to be evicted in order to make space for the new entry.

NOTE: This function is safe for concurrent access. Writers will block simultaneous readers until function execution has concluded.

func (*SigCache) EvictEntries

func (s *SigCache) EvictEntries(block *wire.MsgBlock)

EvictEntries removes all entries from the SigCache that correspond to the transactions in the given block. The block that is passed should be ProactiveEvictionDepth blocks deep, which is the depth at which the signatures for the transactions within the block are nearly guaranteed to no longer be useful.

EvictEntries wraps the unexported evictEntries method, which is run from a goroutine. evictEntries is only invoked if validSigs is not empty. This avoids starting a new goroutine when there is nothing to evict, such as when syncing is ongoing.

func (*SigCache) Exists

func (s *SigCache) Exists(sigHash chainhash.Hash, sig *ecdsa.Signature, pubKey *secp256k1.PublicKey) bool

Exists returns true if an existing entry of 'sig' over 'sigHash' for public key 'pubKey' is found within the SigCache. Otherwise, false is returned.

NOTE: This function is safe for concurrent access. Readers won't be blocked unless there exists a writer, adding an entry to the SigCache.

type SigHashSerType

type SigHashSerType uint16

SigHashSerType represents the serialization type used when calculating signature hashes.

NOTE: These values were originally a part of transaction serialization which is why there is a gap and they are not zero based. The logic for calculating signature hashes has since been decoupled from transaction serialization logic, but these specific values are still required by consensus, so they must remain unchanged.

type SigHashType

type SigHashType byte

SigHashType represents hash type bits at the end of a signature.

const (
	SigHashAll          SigHashType = 0x1
	SigHashNone         SigHashType = 0x2
	SigHashSingle       SigHashType = 0x3
	SigHashAnyOneCanPay SigHashType = 0x80
)

Hash type bits from the end of a signature.

Directories

Path Synopsis
Package stdaddr provides facilities for working with human-readable Decred payment addresses.
Package stdaddr provides facilities for working with human-readable Decred payment addresses.
Package stdscript provides facilities for working with standard scripts.
Package stdscript provides facilities for working with standard scripts.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL