Documentation ¶
Overview ¶
Package txscript implements the bitcoin transaction script language.
A complete description of the script language used by bitcoin can be found at https://en.bitcoin.it/wiki/Script. The following only serves as a quick overview to provide information on how to use the package.
This package provides data structures and functions to parse and execute bitcoin transaction scripts.
Script Overview ¶
Bitcoin transaction scripts are written in a stack-base, FORTH-like language.
The bitcoin 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 Bitcoin 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 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 bitcoins.
Errors ¶
Errors returned by this package are of type txscript.Error. This allows the caller to programmatically determine the specific error by examining the ErrorCode field of the type asserted txscript.Error while still providing rich error messages with contextual information. A convenience function named IsErrorCode is also provided to allow callers to easily check for a specific error code. See ErrorCode in the package documentation for a full list.
Index ¶
- Constants
- Variables
- func CalcMultiSigStats(script []byte) (int, int, error)
- func CalcSignatureHash(script []byte, hashType SigHashType, tx *wire.MsgTx, idx int) ([]byte, error)
- func DisasmString(buf []byte) (string, error)
- func GetPreciseSigOpCount(scriptSig, scriptPubKey []byte, isP2SH bool) int
- func GetSigOpCount(script []byte) int
- func IsErrorCode(err error, c ErrorCode) bool
- func IsPayToScriptHash(script []byte) bool
- func IsPushOnlyScript(script []byte) (bool, error)
- func IsUnspendable(pkScript []byte) bool
- func MultiSigScript(pubkeys []*util.AddressPubKey, nrequired int) ([]byte, error)
- func NullDataScript(data []byte) ([]byte, error)
- func PayToAddrScript(addr util.Address) ([]byte, error)
- func PushedData(script []byte) ([][]byte, error)
- func RawTxInSignature(tx *wire.MsgTx, idx int, script []byte, hashType SigHashType, ...) ([]byte, error)
- func SignTxOutput(chainParams *dagconfig.Params, tx *wire.MsgTx, idx int, pkScript []byte, ...) ([]byte, error)
- func SignatureScript(tx *wire.MsgTx, idx int, script []byte, hashType SigHashType, ...) ([]byte, error)
- type AtomicSwapDataPushes
- type Engine
- func (vm *Engine) CheckErrorCondition(finalScript bool) error
- func (vm *Engine) DisasmPC() (string, error)
- func (vm *Engine) DisasmScript(idx int) (string, error)
- func (vm *Engine) Execute() (err error)
- func (vm *Engine) GetAltStack() [][]byte
- func (vm *Engine) GetStack() [][]byte
- func (vm *Engine) SetAltStack(data [][]byte)
- func (vm *Engine) SetStack(data [][]byte)
- func (vm *Engine) Step() (done bool, err error)
- type ErrScriptNotCanonical
- type Error
- type ErrorCode
- type KeyClosure
- type KeyDB
- type ScriptBuilder
- func (b *ScriptBuilder) AddData(data []byte) *ScriptBuilder
- func (b *ScriptBuilder) AddFullData(data []byte) *ScriptBuilder
- func (b *ScriptBuilder) AddInt64(val int64) *ScriptBuilder
- func (b *ScriptBuilder) AddOp(opcode byte) *ScriptBuilder
- func (b *ScriptBuilder) AddOps(opcodes []byte) *ScriptBuilder
- func (b *ScriptBuilder) Reset() *ScriptBuilder
- func (b *ScriptBuilder) Script() ([]byte, error)
- type ScriptClass
- type ScriptClosure
- type ScriptDB
- type ScriptFlags
- type ScriptInfo
- type SigCache
- type SigHashType
Examples ¶
Constants ¶
const ( // MaxStackSize is the maximum combined height of stack and alt stack // during execution. MaxStackSize = 244 // MaxScriptSize is the maximum allowed length of a raw script. MaxScriptSize = 10000 )
const ( Op0 = 0x00 // 0 OpFalse = 0x00 // 0 - AKA Op0 OpData1 = 0x01 // 1 OpData2 = 0x02 // 2 OpData3 = 0x03 // 3 OpData4 = 0x04 // 4 OpData5 = 0x05 // 5 OpData6 = 0x06 // 6 OpData7 = 0x07 // 7 OpData8 = 0x08 // 8 OpData9 = 0x09 // 9 OpData10 = 0x0a // 10 OpData11 = 0x0b // 11 OpData12 = 0x0c // 12 OpData13 = 0x0d // 13 OpData14 = 0x0e // 14 OpData15 = 0x0f // 15 OpData16 = 0x10 // 16 OpData17 = 0x11 // 17 OpData18 = 0x12 // 18 OpData19 = 0x13 // 19 OpData20 = 0x14 // 20 OpData21 = 0x15 // 21 OpData22 = 0x16 // 22 OpData23 = 0x17 // 23 OpData24 = 0x18 // 24 OpData25 = 0x19 // 25 OpData26 = 0x1a // 26 OpData27 = 0x1b // 27 OpData28 = 0x1c // 28 OpData29 = 0x1d // 29 OpData30 = 0x1e // 30 OpData31 = 0x1f // 31 OpData32 = 0x20 // 32 OpData33 = 0x21 // 33 OpData34 = 0x22 // 34 OpData35 = 0x23 // 35 OpData36 = 0x24 // 36 OpData37 = 0x25 // 37 OpData38 = 0x26 // 38 OpData39 = 0x27 // 39 OpData40 = 0x28 // 40 OpData41 = 0x29 // 41 OpData42 = 0x2a // 42 OpData43 = 0x2b // 43 OpData44 = 0x2c // 44 OpData45 = 0x2d // 45 OpData46 = 0x2e // 46 OpData47 = 0x2f // 47 OpData48 = 0x30 // 48 OpData49 = 0x31 // 49 OpData50 = 0x32 // 50 OpData51 = 0x33 // 51 OpData52 = 0x34 // 52 OpData53 = 0x35 // 53 OpData54 = 0x36 // 54 OpData55 = 0x37 // 55 OpData56 = 0x38 // 56 OpData57 = 0x39 // 57 OpData58 = 0x3a // 58 OpData59 = 0x3b // 59 OpData60 = 0x3c // 60 OpData61 = 0x3d // 61 OpData62 = 0x3e // 62 OpData63 = 0x3f // 63 OpData64 = 0x40 // 64 OpData65 = 0x41 // 65 OpData66 = 0x42 // 66 OpData67 = 0x43 // 67 OpData68 = 0x44 // 68 OpData69 = 0x45 // 69 OpData70 = 0x46 // 70 OpData71 = 0x47 // 71 OpData72 = 0x48 // 72 OpData73 = 0x49 // 73 OpData74 = 0x4a // 74 OpData75 = 0x4b // 75 OpPushData1 = 0x4c // 76 OpPushData2 = 0x4d // 77 OpPushData4 = 0x4e // 78 Op1Negate = 0x4f // 79 OpReserved = 0x50 // 80 Op1 = 0x51 // 81 - AKA OpTrue OpTrue = 0x51 // 81 Op2 = 0x52 // 82 Op3 = 0x53 // 83 Op4 = 0x54 // 84 Op5 = 0x55 // 85 Op6 = 0x56 // 86 Op7 = 0x57 // 87 Op8 = 0x58 // 88 Op9 = 0x59 // 89 Op10 = 0x5a // 90 Op11 = 0x5b // 91 Op12 = 0x5c // 92 Op13 = 0x5d // 93 Op14 = 0x5e // 94 Op15 = 0x5f // 95 Op16 = 0x60 // 96 OpNop = 0x61 // 97 OpVer = 0x62 // 98 OpIf = 0x63 // 99 OpNotIf = 0x64 // 100 OpVerIf = 0x65 // 101 OpVerNotIf = 0x66 // 102 OpElse = 0x67 // 103 OpEndIf = 0x68 // 104 OpVerify = 0x69 // 105 OpReturn = 0x6a // 106 OpToAltStack = 0x6b // 107 OpFromAltStack = 0x6c // 108 Op2Drop = 0x6d // 109 Op2Dup = 0x6e // 110 Op3Dup = 0x6f // 111 Op2Over = 0x70 // 112 Op2Rot = 0x71 // 113 Op2Swap = 0x72 // 114 OpIfDup = 0x73 // 115 OpDepth = 0x74 // 116 OpDrop = 0x75 // 117 OpDup = 0x76 // 118 OpNip = 0x77 // 119 OpOver = 0x78 // 120 OpPick = 0x79 // 121 OpRoll = 0x7a // 122 OpRot = 0x7b // 123 OpSwap = 0x7c // 124 OpTuck = 0x7d // 125 OpCat = 0x7e // 126 OpSubStr = 0x7f // 127 OpLeft = 0x80 // 128 OpRight = 0x81 // 129 OpSize = 0x82 // 130 OpInvert = 0x83 // 131 OpAnd = 0x84 // 132 OpOr = 0x85 // 133 OpXor = 0x86 // 134 OpEqual = 0x87 // 135 OpEqualVerify = 0x88 // 136 OpReserved1 = 0x89 // 137 OpReserved2 = 0x8a // 138 Op1Add = 0x8b // 139 Op1Sub = 0x8c // 140 Op2Mul = 0x8d // 141 Op2Div = 0x8e // 142 OpNegate = 0x8f // 143 OpAbs = 0x90 // 144 OpNot = 0x91 // 145 Op0NotEqual = 0x92 // 146 OpAdd = 0x93 // 147 OpSub = 0x94 // 148 OpMul = 0x95 // 149 OpDiv = 0x96 // 150 OpMod = 0x97 // 151 OpLShift = 0x98 // 152 OpRShift = 0x99 // 153 OpBoolAnd = 0x9a // 154 OpBoolOr = 0x9b // 155 OpNumEqual = 0x9c // 156 OpNumEqualVerify = 0x9d // 157 OpNumNotEqual = 0x9e // 158 OpLessThan = 0x9f // 159 OpGreaterThan = 0xa0 // 160 OpLessThanOrEqual = 0xa1 // 161 OpGreaterThanOrEqual = 0xa2 // 162 OpMin = 0xa3 // 163 OpMax = 0xa4 // 164 OpWithin = 0xa5 // 165 OpRipeMD160 = 0xa6 // 166 OpSHA1 = 0xa7 // 167 OpSHA256 = 0xa8 // 168 OpHash160 = 0xa9 // 169 OpHash256 = 0xaa // 170 OpUnknown171 = 0xab // 171 OpCheckSig = 0xac // 172 OpCheckSigVerify = 0xad // 173 OpCheckMultiSig = 0xae // 174 OpCheckMultiSigVerify = 0xaf // 175 OpCheckLockTimeVerify = 0xb0 // 176 OpCheckSequenceVerify = 0xb1 // 177 OpNop1 = 0xb2 // 178 OpNop2 = 0xb3 // 179 OpNop3 = 0xb4 // 180 OpNop4 = 0xb5 // 181 OpNop5 = 0xb6 // 182 OpNop6 = 0xb7 // 183 OpNop7 = 0xb8 // 184 OpNop8 = 0xb9 // 185 OpNop9 = 0xba // 186 OpNop10 = 0xbb // 187 OpUnknown188 = 0xbc // 188 OpUnknown189 = 0xbd // 189 OpUnknown190 = 0xbe // 190 OpUnknown191 = 0xbf // 191 OpUnknown192 = 0xc0 // 192 OpUnknown193 = 0xc1 // 193 OpUnknown194 = 0xc2 // 194 OpUnknown195 = 0xc3 // 195 OpUnknown196 = 0xc4 // 196 OpUnknown197 = 0xc5 // 197 OpUnknown198 = 0xc6 // 198 OpUnknown199 = 0xc7 // 199 OpUnknown200 = 0xc8 // 200 OpUnknown201 = 0xc9 // 201 OpUnknown202 = 0xca // 202 OpUnknown203 = 0xcb // 203 OpUnknown204 = 0xcc // 204 OpUnknown205 = 0xcd // 205 OpUnknown206 = 0xce // 206 OpUnknown207 = 0xcf // 207 OpUnknown208 = 0xd0 // 208 OpUnknown209 = 0xd1 // 209 OpUnknown210 = 0xd2 // 210 OpUnknown211 = 0xd3 // 211 OpUnknown212 = 0xd4 // 212 OpUnknown213 = 0xd5 // 213 OpUnknown214 = 0xd6 // 214 OpUnknown215 = 0xd7 // 215 OpUnknown216 = 0xd8 // 216 OpUnknown217 = 0xd9 // 217 OpUnknown218 = 0xda // 218 OpUnknown219 = 0xdb // 219 OpUnknown220 = 0xdc // 220 OpUnknown221 = 0xdd // 221 OpUnknown222 = 0xde // 222 OpUnknown223 = 0xdf // 223 OpUnknown224 = 0xe0 // 224 OpUnknown225 = 0xe1 // 225 OpUnknown226 = 0xe2 // 226 OpUnknown227 = 0xe3 // 227 OpUnknown228 = 0xe4 // 228 OpUnknown229 = 0xe5 // 229 OpUnknown230 = 0xe6 // 230 OpUnknown231 = 0xe7 // 231 OpUnknown232 = 0xe8 // 232 OpUnknown233 = 0xe9 // 233 OpUnknown234 = 0xea // 234 OpUnknown235 = 0xeb // 235 OpUnknown236 = 0xec // 236 OpUnknown237 = 0xed // 237 OpUnknown238 = 0xee // 238 OpUnknown239 = 0xef // 239 OpUnknown240 = 0xf0 // 240 OpUnknown241 = 0xf1 // 241 OpUnknown242 = 0xf2 // 242 OpUnknown243 = 0xf3 // 243 OpUnknown244 = 0xf4 // 244 OpUnknown245 = 0xf5 // 245 OpUnknown246 = 0xf6 // 246 OpUnknown247 = 0xf7 // 247 OpUnknown248 = 0xf8 // 248 OpUnknown249 = 0xf9 // 249 OpSmallInteger = 0xfa // 250 - bitcoin core internal OpPubKeys = 0xfb // 251 - bitcoin core internal OpUnknown252 = 0xfc // 252 OpPubKeyHash = 0xfd // 253 - bitcoin core internal OpPubKey = 0xfe // 254 - bitcoin core internal OpInvalidOpCode = 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 BTC scripts.
const ( OpCondFalse = 0 OpCondTrue = 1 OpCondSkip = 2 )
Conditional execution constants.
const ( MaxOpsPerScript = 201 // Max number of non-push operations. MaxPubKeysPerMultiSig = 20 // Multisig can't have more sigs than this. MaxScriptElementSize = 520 // Max bytes pushable to the stack. )
These are the constants specified for maximums in individual scripts.
const ( // MaxDataCarrierSize is the maximum number of bytes allowed in pushed // data to be considered a nulldata transaction MaxDataCarrierSize = 80 // StandardVerifyFlags are the script flags which are used when // executing transaction scripts to enforce additional checks which // are required for the script to be considered standard. These checks // help reduce issues related to transaction malleability as well as // allow pay-to-script hash transactions. Note these flags are // different than what is required for the consensus rules in that they // are more strict. // // TODO: This definition does not belong here. It belongs in a policy // package. StandardVerifyFlags = ScriptDiscourageUpgradableNops )
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 )
Variables ¶
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 CalcMultiSigStats ¶
CalcMultiSigStats returns the number of public keys and signatures from a multi-signature transaction script. The passed script MUST already be known to be a multi-signature script.
func CalcSignatureHash ¶
func CalcSignatureHash(script []byte, hashType SigHashType, tx *wire.MsgTx, idx int) ([]byte, error)
CalcSignatureHash will, given a script and hash type for the current script engine instance, calculate the signature hash to be used for signing and verification.
func DisasmString ¶
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.
func GetPreciseSigOpCount ¶
GetPreciseSigOpCount returns the number of signature operations in scriptPubKey. If p2sh 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.
func GetSigOpCount ¶
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.
func IsErrorCode ¶
IsErrorCode returns whether or not the provided error is a script error with the provided error code.
func IsPayToScriptHash ¶
IsPayToScriptHash returns true if the script is in the standard pay-to-script-hash (P2SH) format, false otherwise.
func IsPushOnlyScript ¶
IsPushOnlyScript returns whether or not the passed script only pushes data.
False will be returned when the script does not parse.
func IsUnspendable ¶
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.
func MultiSigScript ¶
func MultiSigScript(pubkeys []*util.AddressPubKey, nrequired int) ([]byte, error)
MultiSigScript returns a valid script for a multisignature redemption where nrequired of the keys in pubkeys are required to have signed the transaction for success. An Error with the error code ErrTooManyRequiredSigs will be returned if nrequired is larger than the number of keys provided.
func NullDataScript ¶
NullDataScript creates a provably-prunable script containing OP_RETURN followed by the passed data. An Error with the error code ErrTooMuchNullData will be returned if the length of the passed data exceeds MaxDataCarrierSize.
func PayToAddrScript ¶
PayToAddrScript creates a new script to pay a transaction output to a the specified address.
Example ¶
This example demonstrates creating a script which pays to a bitcoin address. It also prints the created script hex and uses the DisasmString function to display the disassembled script.
package main import ( "fmt" "github.com/daglabs/btcd/txscript" "github.com/daglabs/btcd/util" ) func main() { // Parse the address to send the coins to into a util.Address // which is useful to ensure the accuracy of the address and determine // the address type. It is also required for the upcoming call to // PayToAddrScript. addressStr := "dagcoin:qqfgqp8l9l90zwetj84k2jcac2m8falvvy9uastr55" address, err := util.DecodeAddress(addressStr, util.Bech32PrefixDAGCoin) if err != nil { fmt.Println(err) return } // Create a public key script that pays to the address. script, err := txscript.PayToAddrScript(address) if err != nil { fmt.Println(err) return } fmt.Printf("Script Hex: %x\n", script) disasm, err := txscript.DisasmString(script) if err != nil { fmt.Println(err) return } fmt.Println("Script Disassembly:", disasm) }
Output: Script Hex: 76a914128004ff2fcaf13b2b91eb654b1dc2b674f7ec6188ac Script Disassembly: OP_DUP OP_HASH160 128004ff2fcaf13b2b91eb654b1dc2b674f7ec61 OP_EQUALVERIFY OP_CHECKSIG
func PushedData ¶
PushedData returns an array of byte slices containing any pushed data found in the passed script. This includes OP_0, but not OP_1 - OP_16.
func RawTxInSignature ¶
func RawTxInSignature(tx *wire.MsgTx, idx int, script []byte, hashType SigHashType, key *btcec.PrivateKey) ([]byte, error)
RawTxInSignature returns the serialized ECDSA signature for the input idx of the given transaction, with hashType appended to it.
func SignTxOutput ¶
func SignTxOutput(chainParams *dagconfig.Params, tx *wire.MsgTx, idx int, pkScript []byte, hashType SigHashType, kdb KeyDB, sdb ScriptDB, previousScript []byte) ([]byte, error)
SignTxOutput signs output idx of the given tx to resolve the script given in pkScript with a signature type of hashType. Any keys required will be looked up by calling getKey() with the string of the given address. Any pay-to-script-hash signatures will be similarly looked up by calling getScript. If previousScript is provided then the results in previousScript will be merged in a type-dependent manner with the newly generated. signature script.
Example ¶
This example demonstrates manually creating and signing a redeem transaction.
package main import ( "encoding/hex" "fmt" "github.com/daglabs/btcd/btcec" "github.com/daglabs/btcd/dagconfig" "github.com/daglabs/btcd/dagconfig/daghash" "github.com/daglabs/btcd/txscript" "github.com/daglabs/btcd/util" "github.com/daglabs/btcd/wire" ) func main() { // Ordinarily the private key would come from whatever storage mechanism // is being used, but for this example just hard code it. privKeyBytes, err := hex.DecodeString("22a47fa09a223f2aa079edf85a7c2" + "d4f8720ee63e502ee2869afab7de234b80c") if err != nil { fmt.Println(err) return } privKey, pubKey := btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes) pubKeyHash := util.Hash160(pubKey.SerializeCompressed()) addr, err := util.NewAddressPubKeyHash(pubKeyHash, util.Bech32PrefixDAGCoin) if err != nil { fmt.Println(err) return } // For this example, create a fake transaction that represents what // would ordinarily be the real transaction that is being spent. It // contains a single output that pays to address in the amount of 1 BTC. prevOut := wire.NewOutPoint(&daghash.TxID{}, ^uint32(0)) txIn := wire.NewTxIn(prevOut, []byte{txscript.Op0, txscript.Op0}) pkScript, err := txscript.PayToAddrScript(addr) if err != nil { fmt.Println(err) return } txOut := wire.NewTxOut(100000000, pkScript) originTx := wire.NewNativeMsgTx(wire.TxVersion, []*wire.TxIn{txIn}, []*wire.TxOut{txOut}) originTxID := originTx.TxID() // Create the transaction to redeem the fake transaction. // Add the input(s) the redeeming transaction will spend. There is no // signature script at this point since it hasn't been created or signed // yet, hence nil is provided for it. prevOut = wire.NewOutPoint(&originTxID, 0) txIn = wire.NewTxIn(prevOut, nil) // Ordinarily this would contain that actual destination of the funds, // but for this example don't bother. txOut = wire.NewTxOut(0, nil) redeemTx := wire.NewNativeMsgTx(wire.TxVersion, []*wire.TxIn{txIn}, []*wire.TxOut{txOut}) // Sign the redeeming transaction. lookupKey := func(a util.Address) (*btcec.PrivateKey, bool, error) { // Ordinarily this function would involve looking up the private // key for the provided address, but since the only thing being // signed in this example uses the address associated with the // private key from above, simply return it with the compressed // flag set since the address is using the associated compressed // public key. // // NOTE: If you want to prove the code is actually signing the // transaction properly, uncomment the following line which // intentionally returns an invalid key to sign with, which in // turn will result in a failure during the script execution // when verifying the signature. // // privKey.D.SetInt64(12345) // return privKey, true, nil } // Notice that the script database parameter is nil here since it isn't // used. It must be specified when pay-to-script-hash transactions are // being signed. sigScript, err := txscript.SignTxOutput(&dagconfig.MainNetParams, redeemTx, 0, originTx.TxOut[0].PkScript, txscript.SigHashAll, txscript.KeyClosure(lookupKey), nil, nil) if err != nil { fmt.Println(err) return } redeemTx.TxIn[0].SignatureScript = sigScript // Prove that the transaction has been validly signed by executing the // script pair. flags := txscript.ScriptDiscourageUpgradableNops vm, err := txscript.NewEngine(originTx.TxOut[0].PkScript, redeemTx, 0, flags, nil) if err != nil { fmt.Println(err) return } if err := vm.Execute(); err != nil { fmt.Println(err) return } fmt.Println("Transaction successfully signed") }
Output: Transaction successfully signed
func SignatureScript ¶
func SignatureScript(tx *wire.MsgTx, idx int, script []byte, hashType SigHashType, privKey *btcec.PrivateKey, compress bool) ([]byte, error)
SignatureScript creates an input signature script for tx to spend BTC sent from a previous output to the owner of privKey. tx must include all transaction inputs and outputs, however txin scripts are allowed to be filled or empty. The returned script is calculated to be used as the idx'th txin sigscript for tx. script is the PkScript of the previous output being used as the idx'th input. privKey is serialized in either a compressed or uncompressed format based on compress. This format must match the same format used to generate the payment address, or the script validation will fail.
Types ¶
type AtomicSwapDataPushes ¶
type AtomicSwapDataPushes struct { RecipientHash160 [20]byte RefundHash160 [20]byte SecretHash [32]byte SecretSize int64 LockTime uint64 }
AtomicSwapDataPushes houses the data pushes found in atomic swap contracts.
func ExtractAtomicSwapDataPushes ¶
func ExtractAtomicSwapDataPushes(version uint16, pkScript []byte) (*AtomicSwapDataPushes, error)
ExtractAtomicSwapDataPushes returns the data pushes from an atomic swap contract. If the script is not an atomic swap contract, ExtractAtomicSwapDataPushes returns (nil, nil). Non-nil errors are returned for unparsable scripts.
NOTE: Atomic swaps are not considered standard script types by the dcrd mempool policy and should be used with P2SH. The atomic swap format is also expected to change to use a more secure hash function in the future.
This function is only defined in the txscript package due to API limitations which prevent callers using txscript to parse nonstandard scripts.
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, 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 ¶
CheckErrorCondition returns nil if the running script has ended and was successful, leaving a a true boolean on the stack. An error otherwise, including if the script has not finished.
func (*Engine) DisasmPC ¶
DisasmPC returns the string for the disassembly of the opcode that will be next to execute when Step() is called.
func (*Engine) DisasmScript ¶
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.
func (*Engine) Execute ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
Step will execute the next instruction and move 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 ¶
Error identifies a script-related error. It is used to indicate three classes of errors:
- Script execution failures due to violating one of the many requirements imposed by the script engine or evaluating to false
- Improper API usage by callers
- Internal consistency check failures
The caller can use type assertions on the returned errors to access the ErrorCode field to ascertain the specific reason for the error. As an additional convenience, the caller may make use of the IsErrorCode function to check for a specific error code.
type ErrorCode ¶
type ErrorCode int
ErrorCode identifies a kind of script error.
const ( // ErrInternal is returned if internal consistency checks fail. In // practice this error should never be seen as it would mean there is an // error in the engine logic. ErrInternal ErrorCode = iota // ErrInvalidFlags is returned when the passed flags to NewEngine // contain an invalid combination. ErrInvalidFlags // ErrInvalidIndex is returned when an out-of-bounds index is passed to // a function. ErrInvalidIndex // ErrUnsupportedAddress is returned when a concrete type that // implements a util.Address is not a supported type. ErrUnsupportedAddress // ErrNotMultisigScript is returned from CalcMultiSigStats when the // provided script is not a multisig script. ErrNotMultisigScript // ErrTooManyRequiredSigs is returned from MultiSigScript when the // specified number of required signatures is larger than the number of // provided public keys. ErrTooManyRequiredSigs // ErrTooMuchNullData is returned from NullDataScript when the length of // the provided data exceeds MaxDataCarrierSize. ErrTooMuchNullData // ErrEarlyReturn is returned when OP_RETURN is executed in the script. ErrEarlyReturn // ErrEmptyStack is returned when the script evaluated without error, // but terminated with an empty top stack element. ErrEmptyStack // ErrEvalFalse is returned when the script evaluated without error but // terminated with a false top stack element. ErrEvalFalse // ErrScriptUnfinished is returned when CheckErrorCondition is called on // a script that has not finished executing. 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 // ErrScriptTooBig is returned if a script is larger than MaxScriptSize. ErrScriptTooBig // ErrElementTooBig is returned if the size of an element to be pushed // to the stack is over MaxScriptElementSize. ErrElementTooBig // ErrTooManyOperations is returned if a script has more than // MaxOpsPerScript opcodes that do not push data. ErrTooManyOperations // ErrStackOverflow is returned when stack and altstack combined depth // is over the limit. ErrStackOverflow // ErrInvalidPubKeyCount is returned when the number of public keys // specified for a multsig is either negative or greater than // MaxPubKeysPerMultiSig. 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 // ErrNumberTooBig 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 code. ErrNumberTooBig // 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 // 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 // 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 // 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 // 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 // ErrDisabledOpcode is returned when a disabled opcode is encountered // in a script. ErrDisabledOpcode // ErrReservedOpcode is returned when an opcode marked as reserved // is encountered in a script. ErrReservedOpcode // ErrMalformedPush is returned when a data push opcode tries to push // more bytes than are left in the script. ErrMalformedPush // ErrInvalidStackOperation is returned when a stack operation is // attempted with a number that is invalid for the current stack size. 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 // ErrMinimalData is returned when the script contains // push operations that do not use the minimal opcode required. ErrMinimalData // ErrInvalidSigHashType is returned when a signature hash type is not // one of the supported types. ErrInvalidSigHashType // ErrInvalidSigHashSingleIndex is returned what a signature of type // SigHashSingle points to a non-existing output ErrInvalidSigHashSingleIndex // ErrSigDER is returned when a signature is not a canonically-encoded // DER signature. ErrSigDER // ErrSigHighS is returned when the ScriptVerifyLowS flag is set and the // script contains any signatures whose S values are higher than the // half order. ErrSigHighS // ErrNotPushOnly is returned when a script that is required to only // push data to the stack performs other operations. ErrNotPushOnly // ErrPubKeyFormat is returned when the script contains invalid public keys. // A valid pubkey should be in uncompressed format as a 64 byte string prefixed with 0x04, // or to be in compressed format as a 32 byte string prefixed with 0x02 or 0x03 to signal oddness. ErrPubKeyFormat // ErrCleanStack is returned when after evalution, the stack // contains more than one element. ErrCleanStack // ErrNullFail is returned when signatures are not empty // on failed checksig or checkmultisig operations. ErrNullFail // ErrDiscourageUpgradableNOPs is returned when the // ScriptDiscourageUpgradableNops flag is set and a NOP opcode is // encountered in a script. ErrDiscourageUpgradableNOPs // ErrNegativeLockTime is returned when a script contains an opcode that // interprets a negative lock time. 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 // ErrMinimalIf is returned if the operand of an OP_IF/OP_NOTIF // is not either an empty vector or [0x01]. ErrMinimalIf )
These constants are used to identify a specific Error.
type KeyClosure ¶
KeyClosure implements KeyDB with a closure.
func (KeyClosure) GetKey ¶
func (kc KeyClosure) GetKey(address util.Address) (*btcec.PrivateKey, bool, error)
GetKey implements KeyDB by returning the result of calling the closure.
type KeyDB ¶
KeyDB is an interface type provided to SignTxOutput, it encapsulates any user state required to get the private keys for an address.
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 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) AddFullData ¶
func (b *ScriptBuilder) AddFullData(data []byte) *ScriptBuilder
AddFullData 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) 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 ScriptClass ¶
type ScriptClass byte
ScriptClass is an enumeration for the list of standard types of script.
const ( NonStandardTy ScriptClass = iota // None of the recognized forms. PubKeyTy // Pay pubkey. PubKeyHashTy // Pay pubkey hash. ScriptHashTy // Pay to script hash. MultiSigTy // Multi signature. NullDataTy // Empty data-only (provably prunable). )
Classes of script payment known about in the blockDAG.
func ExtractPkScriptAddrs ¶
func ExtractPkScriptAddrs(pkScript []byte, chainParams *dagconfig.Params) (ScriptClass, []util.Address, int, error)
ExtractPkScriptAddrs returns the type of script, addresses and required signatures associated with the passed PkScript. Note that it only works for 'standard' transaction script types. Any data such as public keys which are invalid are omitted from the results.
Example ¶
This example demonstrates extracting information from a standard public key script.
package main import ( "encoding/hex" "fmt" "github.com/daglabs/btcd/dagconfig" "github.com/daglabs/btcd/txscript" ) func main() { // Start with a standard pay-to-pubkey-hash script. scriptHex := "76a914128004ff2fcaf13b2b91eb654b1dc2b674f7ec6188ac" script, err := hex.DecodeString(scriptHex) if err != nil { fmt.Println(err) return } // Extract and print details from the script. scriptClass, addresses, reqSigs, err := txscript.ExtractPkScriptAddrs( script, &dagconfig.MainNetParams) if err != nil { fmt.Println(err) return } fmt.Println("Script Class:", scriptClass) fmt.Println("Addresses:", addresses) fmt.Println("Required Signatures:", reqSigs) }
Output: Script Class: pubkeyhash Addresses: [dagcoin:qqfgqp8l9l90zwetj84k2jcac2m8falvvy9uastr55] Required Signatures: 1
func GetScriptClass ¶
func GetScriptClass(script []byte) ScriptClass
GetScriptClass returns the class of the script passed.
NonStandardTy will be returned when the script does not parse.
func (ScriptClass) String ¶
func (t ScriptClass) String() string
String implements the Stringer interface by returning the name of the enum script class. If the enum is invalid then "Invalid" will be returned.
type ScriptClosure ¶
ScriptClosure implements ScriptDB with a closure.
type ScriptDB ¶
ScriptDB is an interface type provided to SignTxOutput, it encapsulates any user state required to get the scripts for an pay-to-script-hash address.
type ScriptFlags ¶
type ScriptFlags uint32
ScriptFlags is a bitmask defining additional operations or tests that will be done when executing a script pair.
const ( // ScriptNoFlags is used when you want to use ScriptFlags without raising any flags ScriptNoFlags ScriptFlags = 0 // ScriptDiscourageUpgradableNops defines whether to verify that // NOP1 through NOP10 are reserved for future soft-fork 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 )
type ScriptInfo ¶
type ScriptInfo struct { // PkScriptClass is the class of the public key script and is equivalent // to calling GetScriptClass on it. PkScriptClass ScriptClass // NumInputs is the number of inputs provided by the public key script. NumInputs int // ExpectedInputs is the number of outputs required by the signature // script and any pay-to-script-hash scripts. The number will be -1 if // unknown. ExpectedInputs int // SigOps is the number of signature operations in the script pair. SigOps int }
ScriptInfo houses information about a script pair that is determined by CalcScriptInfo.
func CalcScriptInfo ¶
func CalcScriptInfo(sigScript, pkScript []byte, isP2SH bool) (*ScriptInfo, error)
CalcScriptInfo returns a structure providing data about the provided script pair. It will error if the pair is in someway invalid such that they can not be analysed, i.e. if they do not parse or the pkScript is not a push-only script
type SigCache ¶
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 ¶
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 ¶
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) Exists ¶
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 SigHashType ¶
type SigHashType uint32
SigHashType represents hash type bits at the end of a signature.
const ( SigHashOld SigHashType = 0x0 SigHashAll SigHashType = 0x1 SigHashNone SigHashType = 0x2 SigHashSingle SigHashType = 0x3 SigHashAnyOneCanPay SigHashType = 0x80 )
Hash type bits from the end of a signature.