比特币使用脚本系统来处理交易。脚本有着类Forth语言、简单、基于堆栈以及从左向右处理的特点。脚本故意限定为非图灵完备的,没有循环计算功能。
比特币中脚本最常用的是pubkeyhash脚本,即大家常说的P2PKH交易,还有一些其他的交易。如下:
func typeOfScript(pops []parsedOpcode) ScriptClass { if isPubkey(pops) { return PubKeyTy } else if isPubkeyHash(pops) { return PubKeyHashTy } else if isWitnessPubKeyHash(pops) { return WitnessV0PubKeyHashTy } else if isScriptHash(pops) { return ScriptHashTy } else if isWitnessScriptHash(pops) { return WitnessV0ScriptHashTy } else if isMultiSig(pops) { return MultiSigTy } else if isNullData(pops) { return NullDataTy } return NonStandardTy }
各种脚本验证方法,如下:
// isPubkey returns true if the script passed is a pay-to-pubkey transaction, // false otherwise. func isPubkey(pops []parsedOpcode) bool { // Valid pubkeys are either 33 or 65 bytes. return len(pops) == 2 && (len(pops[0].data) == 33 || len(pops[0].data) == 65) && pops[1].opcode.value == OP_CHECKSIG } // isPubkeyHash returns true if the script passed is a pay-to-pubkey-hash // transaction, false otherwise. func isPubkeyHash(pops []parsedOpcode) bool { return len(pops) == 5 && pops[0].opcode.value == OP_DUP && pops[1].opcode.value == OP_HASH160 && pops[2].opcode.value == OP_DATA_20 && pops[3].opcode.value == OP_EQUALVERIFY && pops[4].opcode.value == OP_CHECKSIG } // isMultiSig returns true if the passed script is a multisig transaction, false // otherwise. func isMultiSig(pops []parsedOpcode) bool { // The absolute minimum is 1 pubkey: // OP_0/OP_1-16 <pubkey> OP_1 OP_CHECKMULTISIG l := len(pops) if l < 4 { return false } if !isSmallInt(pops[0].opcode) { return false } if !isSmallInt(pops[l-2].opcode) { return false } if pops[l-1].opcode.value != OP_CHECKMULTISIG { return false } // Verify the number of pubkeys specified matches the actual number // of pubkeys provided. if l-2-1 != asSmallInt(pops[l-2].opcode) { return false } for _, pop := range pops[1 : l-2] { // Valid pubkeys are either 33 or 65 bytes. if len(pop.data) != 33 && len(pop.data) != 65 { return false } } return true }txscript/opcode.go文件包含所有的指令,是不包含循环指令的。