比特币全节点Go语言实现BTCD之脚本

比特币使用脚本系统来处理交易。脚本有着类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文件包含所有的指令,是不包含循环指令的。

猜你喜欢

转载自blog.csdn.net/vohyeah/article/details/80704578