请选择 进入手机版 | 继续访问电脑版
开启辅助访问
QQ登录|微信登录|登录 |立即注册

盖茨网区块链技术社区

bitcoin代码中比特币脚本是如何解析的

前面我们将了脚本解析的原理,今天我们从代码的角度来介绍比特币中是如何进行脚本解析的。
比特币的脚本解析首先需要谈的类是Cscript类。该类位于script.h 中


前面我们列举过脚本验证所有操作码,他是位于该文件中enum opcodetype枚举中
  1. /** Script opcodes */
  2. enum opcodetype
  3. {
  4.     // push value
  5.     OP_0 = 0x00,
  6.     OP_FALSE = OP_0,
  7.     OP_PUSHDATA1 = 0x4c,
  8.     OP_PUSHDATA2 = 0x4d,
  9.     OP_PUSHDATA4 = 0x4e,
  10.     OP_1NEGATE = 0x4f,
  11.     OP_RESERVED = 0x50,
  12.     OP_1 = 0x51,
  13.     OP_TRUE=OP_1,
  14.     OP_2 = 0x52,
  15.     OP_3 = 0x53,
  16.     OP_4 = 0x54,
  17.     OP_5 = 0x55,
  18.     OP_6 = 0x56,
  19.     OP_7 = 0x57,
  20.     OP_8 = 0x58,
  21.     OP_9 = 0x59,
  22.     OP_10 = 0x5a,
  23.     OP_11 = 0x5b,
  24.     OP_12 = 0x5c,
  25.     OP_13 = 0x5d,
  26.     OP_14 = 0x5e,
  27.     OP_15 = 0x5f,
  28.     OP_16 = 0x60,

  29.     // control
  30.     OP_NOP = 0x61,
  31.     OP_VER = 0x62,
  32.     OP_IF = 0x63,
  33.     OP_NOTIF = 0x64,
  34.     OP_VERIF = 0x65,
  35.     OP_VERNOTIF = 0x66,
  36.     OP_ELSE = 0x67,
  37.     OP_ENDIF = 0x68,
  38.     OP_VERIFY = 0x69,
  39.     OP_RETURN = 0x6a,

  40.     // stack ops
  41.     OP_TOALTSTACK = 0x6b,
  42.     OP_FROMALTSTACK = 0x6c,
  43.     OP_2DROP = 0x6d,
  44.     OP_2DUP = 0x6e,
  45.     OP_3DUP = 0x6f,
  46.     OP_2OVER = 0x70,
  47.     OP_2ROT = 0x71,
  48.     OP_2SWAP = 0x72,
  49.     OP_IFDUP = 0x73,
  50.     OP_DEPTH = 0x74,
  51.     OP_DROP = 0x75,
  52.     OP_DUP = 0x76,
  53.     OP_NIP = 0x77,
  54.     OP_OVER = 0x78,
  55.     OP_PICK = 0x79,
  56.     OP_ROLL = 0x7a,
  57.     OP_ROT = 0x7b,
  58.     OP_SWAP = 0x7c,
  59.     OP_TUCK = 0x7d,

  60.     // splice ops
  61.     OP_CAT = 0x7e,
  62.     OP_SUBSTR = 0x7f,
  63.     OP_LEFT = 0x80,
  64.     OP_RIGHT = 0x81,
  65.     OP_SIZE = 0x82,

  66.     // bit logic
  67.     OP_INVERT = 0x83,
  68.     OP_AND = 0x84,
  69.     OP_OR = 0x85,
  70.     OP_XOR = 0x86,
  71.     OP_EQUAL = 0x87,
  72.     OP_EQUALVERIFY = 0x88,
  73.     OP_RESERVED1 = 0x89,
  74.     OP_RESERVED2 = 0x8a,

  75.     // numeric
  76.     OP_1ADD = 0x8b,
  77.     OP_1SUB = 0x8c,
  78.     OP_2MUL = 0x8d,
  79.     OP_2DIV = 0x8e,
  80.     OP_NEGATE = 0x8f,
  81.     OP_ABS = 0x90,
  82.     OP_NOT = 0x91,
  83.     OP_0NOTEQUAL = 0x92,

  84.     OP_ADD = 0x93,
  85.     OP_SUB = 0x94,
  86.     OP_MUL = 0x95,
  87.     OP_DIV = 0x96,
  88.     OP_MOD = 0x97,
  89.     OP_LSHIFT = 0x98,
  90.     OP_RSHIFT = 0x99,

  91.     OP_BOOLAND = 0x9a,
  92.     OP_BOOLOR = 0x9b,
  93.     OP_NUMEQUAL = 0x9c,
  94.     OP_NUMEQUALVERIFY = 0x9d,
  95.     OP_NUMNOTEQUAL = 0x9e,
  96.     OP_LESSTHAN = 0x9f,
  97.     OP_GREATERTHAN = 0xa0,
  98.     OP_LESSTHANOREQUAL = 0xa1,
  99.     OP_GREATERTHANOREQUAL = 0xa2,
  100.     OP_MIN = 0xa3,
  101.     OP_MAX = 0xa4,

  102.     OP_WITHIN = 0xa5,

  103.     // crypto
  104.     OP_RIPEMD160 = 0xa6,
  105.     OP_SHA1 = 0xa7,
  106.     OP_SHA256 = 0xa8,
  107.     OP_HASH160 = 0xa9,
  108.     OP_HASH256 = 0xaa,
  109.     OP_CODESEPARATOR = 0xab,
  110.     OP_CHECKSIG = 0xac,
  111.     OP_CHECKSIGVERIFY = 0xad,
  112.     OP_CHECKMULTISIG = 0xae,
  113.     OP_CHECKMULTISIGVERIFY = 0xaf,

  114.     // expansion
  115.     OP_NOP1 = 0xb0,
  116.     OP_CHECKLOCKTIMEVERIFY = 0xb1,
  117.     OP_NOP2 = OP_CHECKLOCKTIMEVERIFY,
  118.     OP_CHECKSEQUENCEVERIFY = 0xb2,
  119.     OP_NOP3 = OP_CHECKSEQUENCEVERIFY,
  120.     OP_NOP4 = 0xb3,
  121.     OP_NOP5 = 0xb4,
  122.     OP_NOP6 = 0xb5,
  123.     OP_NOP7 = 0xb6,
  124.     OP_NOP8 = 0xb7,
  125.     OP_NOP9 = 0xb8,
  126.     OP_NOP10 = 0xb9,


  127.     // template matching params
  128.     OP_SMALLINTEGER = 0xfa,
  129.     OP_PUBKEYS = 0xfb,
  130.     OP_PUBKEYHASH = 0xfd,
  131.     OP_PUBKEY = 0xfe,

  132.     OP_INVALIDOPCODE = 0xff,
  133. };
复制代码


脚本类描述为
  1. class CScript : public CScriptBase
  2. {
  3. protected:
  4.     CScript& push_int64(int64_t n)
  5.     {
  6.         if (n == -1 || (n >= 1 && n <= 16))
  7.         {
  8.             push_back(n + (OP_1 - 1));
  9.         }
  10.         else if (n == 0)
  11.         {
  12.             push_back(OP_0);
  13.         }
  14.         else
  15.         {
  16.             *this << CScriptNum::serialize(n);
  17.         }
  18.         return *this;
  19.     }
  20. public:
  21.     CScript() { }
  22.     CScript(const_iterator pbegin, const_iterator pend) : CScriptBase(pbegin, pend) { }
  23.     CScript(std::vector<unsigned char>::const_iterator pbegin, std::vector<unsigned char>::const_iterator pend) : CScriptBase(pbegin, pend) { }
  24.     CScript(const unsigned char* pbegin, const unsigned char* pend) : CScriptBase(pbegin, pend) { }

  25.     ADD_SERIALIZE_METHODS;

  26.     template <typename Stream, typename Operation>
  27.     inline void SerializationOp(Stream& s, Operation ser_action) {
  28.         READWRITEAS(CScriptBase, *this);
  29.     }

  30.     CScript& operator+=(const CScript& b)
  31.     {
  32.         reserve(size() + b.size());
  33.         insert(end(), b.begin(), b.end());
  34.         return *this;
  35.     }

  36.     friend CScript operator+(const CScript& a, const CScript& b)
  37.     {
  38.         CScript ret = a;
  39.         ret += b;
  40.         return ret;
  41.     }

  42.     CScript(int64_t b)        { operator<<(b); }

  43.     explicit CScript(opcodetype b)     { operator<<(b); }
  44.     explicit CScript(const CScriptNum& b) { operator<<(b); }
  45.     explicit CScript(const std::vector<unsigned char>& b) { operator<<(b); }


  46.     CScript& operator<<(int64_t b) { return push_int64(b); }

  47.     CScript& operator<<(opcodetype opcode)
  48.     {
  49.         if (opcode < 0 || opcode > 0xff)
  50.             throw std::runtime_error("CScript::operator<<(): invalid opcode");
  51.         insert(end(), (unsigned char)opcode);
  52.         return *this;
  53.     }

  54.     CScript& operator<<(const CScriptNum& b)
  55.     {
  56.         *this << b.getvch();
  57.         return *this;
  58.     }

  59.     CScript& operator<<(const std::vector<unsigned char>& b)
  60.     {
  61.         if (b.size() < OP_PUSHDATA1)
  62.         {
  63.             insert(end(), (unsigned char)b.size());
  64.         }
  65.         else if (b.size() <= 0xff)
  66.         {
  67.             insert(end(), OP_PUSHDATA1);
  68.             insert(end(), (unsigned char)b.size());
  69.         }
  70.         else if (b.size() <= 0xffff)
  71.         {
  72.             insert(end(), OP_PUSHDATA2);
  73.             uint8_t _data[2];
  74.             WriteLE16(_data, b.size());
  75.             insert(end(), _data, _data + sizeof(_data));
  76.         }
  77.         else
  78.         {
  79.             insert(end(), OP_PUSHDATA4);
  80.             uint8_t _data[4];
  81.             WriteLE32(_data, b.size());
  82.             insert(end(), _data, _data + sizeof(_data));
  83.         }
  84.         insert(end(), b.begin(), b.end());
  85.         return *this;
  86.     }

  87.     CScript& operator<<(const CScript& b)
  88.     {
  89.         // I'm not sure if this should push the script or concatenate scripts.
  90.         // If there's ever a use for pushing a script onto a script, delete this member fn
  91.         assert(!"Warning: Pushing a CScript onto a CScript with << is probably not intended, use + to concatenate!");
  92.         return *this;
  93.     }


  94.     bool GetOp(const_iterator& pc, opcodetype& opcodeRet, std::vector<unsigned char>& vchRet) const
  95.     {
  96.         return GetScriptOp(pc, end(), opcodeRet, &vchRet);
  97.     }

  98.     bool GetOp(const_iterator& pc, opcodetype& opcodeRet) const
  99.     {
  100.         return GetScriptOp(pc, end(), opcodeRet, nullptr);
  101.     }


  102.     /** Encode/decode small integers: */
  103.     static int DecodeOP_N(opcodetype opcode)
  104.     {
  105.         if (opcode == OP_0)
  106.             return 0;
  107.         assert(opcode >= OP_1 && opcode <= OP_16);
  108.         return (int)opcode - (int)(OP_1 - 1);
  109.     }
  110.     static opcodetype EncodeOP_N(int n)
  111.     {
  112.         assert(n >= 0 && n <= 16);
  113.         if (n == 0)
  114.             return OP_0;
  115.         return (opcodetype)(OP_1+n-1);
  116.     }

  117.     /**
  118.      * Pre-version-0.6, Bitcoin always counted CHECKMULTISIGs
  119.      * as 20 sigops. With pay-to-script-hash, that changed:
  120.      * CHECKMULTISIGs serialized in scriptSigs are
  121.      * counted more accurately, assuming they are of the form
  122.      *  ... OP_N CHECKMULTISIG ...
  123.      */
  124.     unsigned int GetSigOpCount(bool fAccurate) const;

  125.     /**
  126.      * Accurately count sigOps, including sigOps in
  127.      * pay-to-script-hash transactions:
  128.      */
  129.     unsigned int GetSigOpCount(const CScript& scriptSig) const;

  130.     bool IsPayToScriptHash() const;
  131.     bool IsPayToWitnessScriptHash() const;
  132.     bool IsWitnessProgram(int& version, std::vector<unsigned char>& program) const;

  133.     /** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */
  134.     bool IsPushOnly(const_iterator pc) const;
  135.     bool IsPushOnly() const;

  136.     /** Check if the script contains valid OP_CODES */
  137.     bool HasValidOps() const;

  138.     /**
  139.      * Returns whether the script is guaranteed to fail at execution,
  140.      * regardless of the initial stack. This allows outputs to be pruned
  141.      * instantly when entering the UTXO set.
  142.      */
  143.     bool IsUnspendable() const
  144.     {
  145.         return (size() > 0 && *begin() == OP_RETURN) || (size() > MAX_SCRIPT_SIZE);
  146.     }

  147.     void clear()
  148.     {
  149.         // The default prevector::clear() does not release memory
  150.         CScriptBase::clear();
  151.         shrink_to_fit();
  152.     }
  153. };
复制代码
凡是有ADD_SERIALIZE_METHODS;的宏定义该类可以通过“<<”输出到指定类中。
该类重载了很多<<的赋值操作,可以囊括几乎所有的数据类型。


其中比较重要的几个方法
  1.   bool GetOp(const_iterator& pc, opcodetype& opcodeRet, std::vector<unsigned char>& vchRet) const
  2.     {
  3.         return GetScriptOp(pc, end(), opcodeRet, &vchRet);
  4.     }

  5.     bool GetOp(const_iterator& pc, opcodetype& opcodeRet) const
  6.     {
  7.         return GetScriptOp(pc, end(), opcodeRet, nullptr);
  8.     }
复制代码

获得pc指针对应的操作码和操作数。
  1. bool GetScriptOp(CScriptBase::const_iterator& pc, CScriptBase::const_iterator end, opcodetype& opcodeRet, std::vector<unsigned char>* pvchRet)
  2. {
  3.     opcodeRet = OP_INVALIDOPCODE;
  4.     if (pvchRet)
  5.         pvchRet->clear();
  6.     if (pc >= end)
  7.         return false;

  8.     // Read instruction
  9.     if (end - pc < 1)
  10.         return false;
  11.     unsigned int opcode = *pc++;

  12.     // Immediate operand
  13.     if (opcode <= OP_PUSHDATA4)
  14.     {
  15.         unsigned int nSize = 0;
  16.         if (opcode < OP_PUSHDATA1)
  17.         {
  18.             nSize = opcode;
  19.         }
  20.         else if (opcode == OP_PUSHDATA1)
  21.         {
  22.             if (end - pc < 1)
  23.                 return false;
  24.             nSize = *pc++;
  25.         }
  26.         else if (opcode == OP_PUSHDATA2)
  27.         {
  28.             if (end - pc < 2)
  29.                 return false;
  30.             nSize = ReadLE16(&pc[0]);
  31.             pc += 2;
  32.         }
  33.         else if (opcode == OP_PUSHDATA4)
  34.         {
  35.             if (end - pc < 4)
  36.                 return false;
  37.             nSize = ReadLE32(&pc[0]);
  38.             pc += 4;
  39.         }
  40.         if (end - pc < 0 || (unsigned int)(end - pc) < nSize)
  41.             return false;
  42.         if (pvchRet)
  43.             pvchRet->assign(pc, pc + nSize);
  44.         pc += nSize;
  45.     }

  46.     opcodeRet = static_cast<opcodetype>(opcode);
  47.     return true;
  48. }
复制代码
该函数将pc取出,凡是pc小于OP_PUSHDATA4均为push操作,根据pc范围将pc分为1字节,2字节,4字节,并且将pc对于的字节数取出放入pvchret中,同时将pc偏移。


在init.cpp中,是脚本验证的入口。
  1. LogPrintf("Using %u threads for script verification\n", nScriptCheckThreads);
  2.     if (nScriptCheckThreads) {
  3.         for (int i=0; i<nScriptCheckThreads-1; i++)
  4.             threadGroup.create_thread(&ThreadScriptCheck);
  5.     }

  6.     // Start the lightweight task scheduler thread
  7.     CScheduler::Function serviceLoop = boost::bind(&CScheduler::serviceQueue, &scheduler);
  8.     threadGroup.create_thread(boost::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop));
复制代码
该代码创建了nScriptCheckThreads个线程用于验证脚本。


每个线程最终执行的是
  1.     /** Internal function that does bulk of the verification work. */
  2.     bool Loop(bool fMaster = false)
  3.     {
  4.         boost::condition_variable& cond = fMaster ? condMaster : condWorker;
  5.         std::vector<T> vChecks;
  6.         vChecks.reserve(nBatchSize);
  7.         unsigned int nNow = 0;
  8.         bool fOk = true;
  9.         do {
  10.             {
  11.                 boost::unique_lock<boost::mutex> lock(mutex);
  12.                 // first do the clean-up of the previous loop run (allowing us to do it in the same critsect)
  13.                 if (nNow) {
  14.                     fAllOk &= fOk;
  15.                     nTodo -= nNow;
  16.                     if (nTodo == 0 && !fMaster)
  17.                         // We processed the last element; inform the master it can exit and return the result
  18.                         condMaster.notify_one();
  19.                 } else {
  20.                     // first iteration
  21.                     nTotal++;
  22.                 }
  23.                 // logically, the do loop starts here
  24.                 while (queue.empty()) {
  25.                     if (fMaster && nTodo == 0) {
  26.                         nTotal--;
  27.                         bool fRet = fAllOk;
  28.                         // reset the status for new work later
  29.                         if (fMaster)
  30.                             fAllOk = true;
  31.                         // return the current status
  32.                         return fRet;
  33.                     }
  34.                     nIdle++;
  35.                     cond.wait(lock); // wait
  36.                     nIdle--;
  37.                 }
  38.                 // Decide how many work units to process now.
  39.                 // * Do not try to do everything at once, but aim for increasingly smaller batches so
  40.                 //   all workers finish approximately simultaneously.
  41.                 // * Try to account for idle jobs which will instantly start helping.
  42.                 // * Don't do batches smaller than 1 (duh), or larger than nBatchSize.
  43.                 nNow = std::max(1U, std::min(nBatchSize, (unsigned int)queue.size() / (nTotal + nIdle + 1)));
  44.                 vChecks.resize(nNow);
  45.                 for (unsigned int i = 0; i < nNow; i++) {
  46.                     // We want the lock on the mutex to be as short as possible, so swap jobs from the global
  47.                     // queue to the local batch vector instead of copying.
  48.                     vChecks[i].swap(queue.back());
  49.                     queue.pop_back();
  50.                 }
  51.                 // Check whether we need to do work at all
  52.                 fOk = fAllOk;
  53.             }
  54.             // execute work
  55.             for (T& check : vChecks)
  56.                 if (fOk)
  57.                     fOk = check();
  58.             vChecks.clear();
  59.         } while (true);
  60.     }
复制代码
利用条件变量和互斥锁使得多个线程协调工作。
最后执行脚本验证的是该句:check()
该句为()的操作符重载。


内容为:
  1. bool CScriptCheck::operator()() {
  2.     const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
  3.     const CScriptWitness *witness = &ptxTo->vin[nIn].scriptWitness;
  4.     return VerifyScript(scriptSig, m_tx_out.scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, m_tx_out.nValue, cacheStore, *txdata), &error);
  5. }
复制代码
在函数VerifyScript中分别传入了锁定脚本,解锁脚本,和交易类型标志flag。


  1. bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
  2. {
  3.     static const CScriptWitness emptyWitness;
  4.     if (witness == nullptr) {
  5.         witness = &emptyWitness;
  6.     }
  7.     bool hadWitness = false;

  8.     set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);

  9.     if ((flags & SCRIPT_VERIFY_SIGPUSHONLY) != 0 && !scriptSig.IsPushOnly()) {
  10.         return set_error(serror, SCRIPT_ERR_SIG_PUSHONLY);
  11.     }

  12.     std::vector<std::vector<unsigned char> > stack, stackCopy;
  13.     if (!EvalScript(stack, scriptSig, flags, checker, SigVersion::BASE, serror))
  14.         // serror is set
  15.         return false;
  16.     if (flags & SCRIPT_VERIFY_P2SH)
  17.         stackCopy = stack;
  18.     if (!EvalScript(stack, scriptPubKey, flags, checker, SigVersion::BASE, serror))
  19.         // serror is set
  20.         return false;
  21.     if (stack.empty())
  22.         return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
  23.     if (CastToBool(stack.back()) == false)
  24.         return set_error(serror, SCRIPT_ERR_EVAL_FALSE);

  25.     // Bare witness programs
  26.     int witnessversion;
  27.     std::vector<unsigned char> witnessprogram;
  28.     if (flags & SCRIPT_VERIFY_WITNESS) {
  29.         if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
  30.             hadWitness = true;
  31.             if (scriptSig.size() != 0) {
  32.                 // The scriptSig must be _exactly_ CScript(), otherwise we reintroduce malleability.
  33.                 return set_error(serror, SCRIPT_ERR_WITNESS_MALLEATED);
  34.             }
  35.             if (!VerifyWitnessProgram(*witness, witnessversion, witnessprogram, flags, checker, serror)) {
  36.                 return false;
  37.             }
  38.             // Bypass the cleanstack check at the end. The actual stack is obviously not clean
  39.             // for witness programs.
  40.             stack.resize(1);
  41.         }
  42.     }

  43.     // Additional validation for spend-to-script-hash transactions:
  44.     if ((flags & SCRIPT_VERIFY_P2SH) && scriptPubKey.IsPayToScriptHash())
  45.     {
  46.         // scriptSig must be literals-only or validation fails
  47.         if (!scriptSig.IsPushOnly())
  48.             return set_error(serror, SCRIPT_ERR_SIG_PUSHONLY);

  49.         // Restore stack.
  50.         swap(stack, stackCopy);

  51.         // stack cannot be empty here, because if it was the
  52.         // P2SH  HASH <> EQUAL  scriptPubKey would be evaluated with
  53.         // an empty stack and the EvalScript above would return false.
  54.         assert(!stack.empty());

  55.         const valtype& pubKeySerialized = stack.back();
  56.         CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end());
  57.         popstack(stack);

  58.         if (!EvalScript(stack, pubKey2, flags, checker, SigVersion::BASE, serror))
  59.             // serror is set
  60.             return false;
  61.         if (stack.empty())
  62.             return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
  63.         if (!CastToBool(stack.back()))
  64.             return set_error(serror, SCRIPT_ERR_EVAL_FALSE);

  65.         // P2SH witness program
  66.         if (flags & SCRIPT_VERIFY_WITNESS) {
  67.             if (pubKey2.IsWitnessProgram(witnessversion, witnessprogram)) {
  68.                 hadWitness = true;
  69.                 if (scriptSig != CScript() << std::vector<unsigned char>(pubKey2.begin(), pubKey2.end())) {
  70.                     // The scriptSig must be _exactly_ a single push of the redeemScript. Otherwise we
  71.                     // reintroduce malleability.
  72.                     return set_error(serror, SCRIPT_ERR_WITNESS_MALLEATED_P2SH);
  73.                 }
  74.                 if (!VerifyWitnessProgram(*witness, witnessversion, witnessprogram, flags, checker, serror)) {
  75.                     return false;
  76.                 }
  77.                 // Bypass the cleanstack check at the end. The actual stack is obviously not clean
  78.                 // for witness programs.
  79.                 stack.resize(1);
  80.             }
  81.         }
  82.     }

  83.     // The CLEANSTACK check is only performed after potential P2SH evaluation,
  84.     // as the non-P2SH evaluation of a P2SH script will obviously not result in
  85.     // a clean stack (the P2SH inputs remain). The same holds for witness evaluation.
  86.     if ((flags & SCRIPT_VERIFY_CLEANSTACK) != 0) {
  87.         // Disallow CLEANSTACK without P2SH, as otherwise a switch CLEANSTACK->P2SH+CLEANSTACK
  88.         // would be possible, which is not a softfork (and P2SH should be one).
  89.         assert((flags & SCRIPT_VERIFY_P2SH) != 0);
  90.         assert((flags & SCRIPT_VERIFY_WITNESS) != 0);
  91.         if (stack.size() != 1) {
  92.             return set_error(serror, SCRIPT_ERR_CLEANSTACK);
  93.         }
  94.     }

  95.     if (flags & SCRIPT_VERIFY_WITNESS) {
  96.         // We can't check for correct unexpected witness data if P2SH was off, so require
  97.         // that WITNESS implies P2SH. Otherwise, going from WITNESS->P2SH+WITNESS would be
  98.         // possible, which is not a softfork.
  99.         assert((flags & SCRIPT_VERIFY_P2SH) != 0);
  100.         if (!hadWitness && !witness->IsNull()) {
  101.             return set_error(serror, SCRIPT_ERR_WITNESS_UNEXPECTED);
  102.         }
  103.     }

  104.     return set_success(serror);
  105. }
复制代码
该函数比较简单,
  1. if (!EvalScript(stack, scriptSig, flags, checker, SigVersion::BASE, serror))
  2.         // serror is set
  3.         return false;
  4.     if (flags & SCRIPT_VERIFY_P2SH)
  5.         stackCopy = stack;
  6.     if (!EvalScript(stack, scriptPubKey, flags, checker, SigVersion::BASE, serror))
  7.         // serror is set
  8.         return false;
  9.     if (stack.empty())
  10.         return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
  11.     if (CastToBool(stack.back()) == false)
  12.         return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
复制代码
首先将解锁脚本,锁定脚本放入堆栈进行执行,根据执行后堆栈的结果判断是否验证通过,后面在根据flag其他交易类型的分类计算



0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则