mirror of
				https://github.com/bitcoin/bips.git
				synced 2025-11-03 14:19:40 +00:00 
			
		
		
		
	[BIP-119] Remove C++ Spec from BIP-119 entirely.
This commit is contained in:
		
							parent
							
								
									fa09f7f857
								
							
						
					
					
						commit
						cad2b3ee77
					
				@ -163,7 +163,8 @@ forming a "Payment Pool".
 | 
			
		||||
 | 
			
		||||
The below code is the main logic for verifying CHECKTEMPLATEVERIFY, described
 | 
			
		||||
in pythonic pseduocode. The canonical specification for the semantics of
 | 
			
		||||
OP_CHECKTEMPLATEVERIFY can be seen in the reference implementations.
 | 
			
		||||
OP_CHECKTEMPLATEVERIFY as implemented in C++ in the context of Bitcoin Core can
 | 
			
		||||
be seen in the reference implementation.
 | 
			
		||||
 | 
			
		||||
The execution of the opcode is as follows:
 | 
			
		||||
    def execute_bip_119(self):
 | 
			
		||||
@ -236,128 +237,6 @@ optimization.
 | 
			
		||||
        return sha256(r)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
The C++ is below:
 | 
			
		||||
 | 
			
		||||
    case OP_CHECKTEMPLATEVERIFY:
 | 
			
		||||
    {
 | 
			
		||||
        // if flags not enabled; treat as a NOP4
 | 
			
		||||
        if (!(flags & SCRIPT_VERIFY_DEFAULT_CHECK_TEMPLATE_VERIFY_HASH)) {
 | 
			
		||||
            if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
 | 
			
		||||
                return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (stack.size() < 1)
 | 
			
		||||
            return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
 | 
			
		||||
 | 
			
		||||
        // If the argument was not 32 bytes, treat as OP_NOP4:
 | 
			
		||||
        switch (stack.back().size()) {
 | 
			
		||||
            case 32:
 | 
			
		||||
                if (!checker.CheckDefaultCheckTemplateVerifyHash(stack.back())) {
 | 
			
		||||
                    return set_error(serror, SCRIPT_ERR_TEMPLATE_MISMATCH);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                // future upgrade can add semantics for this opcode with different length args
 | 
			
		||||
                // so discourage use when applicable
 | 
			
		||||
                if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
 | 
			
		||||
                    return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
 | 
			
		||||
                }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    break;
 | 
			
		||||
 | 
			
		||||
Where
 | 
			
		||||
 | 
			
		||||
    bool CheckDefaultCheckTemplateVerifyHash(const std::vector<unsigned char>& hash) {
 | 
			
		||||
        return GetDefaultCheckTemplateVerifyHash(current_tx, current_input_index) == uint256(hash);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
The hash is computed as follows, where the outputs_hash and sequences_hash are computed as defined in BIP-341.
 | 
			
		||||
 | 
			
		||||
    /** Compute the (single) SHA256 of the concatenation of all scriptSigs in a tx. */
 | 
			
		||||
    template <class T>
 | 
			
		||||
    uint256 GetScriptSigsSHA256(const T& txTo)
 | 
			
		||||
    {
 | 
			
		||||
        CHashWriter ss(SER_GETHASH, 0);
 | 
			
		||||
        for (const auto& in : txTo.vin) {
 | 
			
		||||
            ss << in.scriptSig;
 | 
			
		||||
        }
 | 
			
		||||
        return ss.GetSHA256();
 | 
			
		||||
    }
 | 
			
		||||
    // not DoS safe, for reference/testing!
 | 
			
		||||
    uint256 GetDefaultCheckTemplateVerifyHash(const CTransaction& tx, uint32_t input_index) {
 | 
			
		||||
        return GetDefaultCheckTemplateVerifyHash(tx, GetOutputsSHA256(tx), GetSequenceSHA256(tx), input_index);
 | 
			
		||||
    }
 | 
			
		||||
    // not DoS safe for reference/testing!
 | 
			
		||||
    uint256 GetDefaultCheckTemplateVerifyHash(const CTransaction& tx, const uint256& outputs_hash, const uint256& sequences_hash,
 | 
			
		||||
                                    const uint32_t input_index) {
 | 
			
		||||
        bool skip_scriptSigs = std::find_if(tx.vin.begin(), tx.vin.end(),
 | 
			
		||||
                [](const CTxIn& c) { return c.scriptSig != CScript(); }) == tx.vin.end();
 | 
			
		||||
        return skip_scriptSigs ? GetDefaultCheckTemplateVerifyHashEmptyScript(tx, outputs_hash, sequences_hash, input_index) :
 | 
			
		||||
            GetDefaultCheckTemplateVerifyHashWithScript(tx, outputs_hash, sequences_hash, GetScriptSigsSHA256(tx), input_index);
 | 
			
		||||
    }
 | 
			
		||||
    // DoS safe, fixed length hash!
 | 
			
		||||
    uint256 GetDefaultCheckTemplateVerifyHashWithScript(const CTransaction& tx, const uint256& outputs_hash, const uint256& sequences_hash,
 | 
			
		||||
                                    const uint256& scriptSig_hash, const uint32_t input_index) {
 | 
			
		||||
        auto h =  CHashWriter(SER_GETHASH, 0)
 | 
			
		||||
            << tx.nVersion
 | 
			
		||||
            << tx.nLockTime
 | 
			
		||||
            << scriptSig_hash
 | 
			
		||||
            << uint32_t(tx.vin.size())
 | 
			
		||||
            << sequences_hash
 | 
			
		||||
            << uint32_t(tx.vout.size())
 | 
			
		||||
            << outputs_hash
 | 
			
		||||
            << input_index;
 | 
			
		||||
        return h.GetSHA256();
 | 
			
		||||
    }
 | 
			
		||||
    // DoS safe, fixed length hash!
 | 
			
		||||
    uint256 GetDefaultCheckTemplateVerifyHashEmptyScript(const CTransaction& tx, const uint256& outputs_hash, const uint256& sequences_hash,
 | 
			
		||||
                                    const uint32_t input_index) {
 | 
			
		||||
        auto h =  CHashWriter(SER_GETHASH, 0)
 | 
			
		||||
            << tx.nVersion
 | 
			
		||||
            << tx.nLockTime
 | 
			
		||||
            << uint32_t(tx.vin.size())
 | 
			
		||||
            << sequences_hash
 | 
			
		||||
            << uint32_t(tx.vout.size())
 | 
			
		||||
            << outputs_hash
 | 
			
		||||
            << input_index;
 | 
			
		||||
        return h.GetSHA256();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    case OP_CHECKTEMPLATEVERIFY:
 | 
			
		||||
    {
 | 
			
		||||
        // if flags not enabled; treat as a NOP4
 | 
			
		||||
        if (!(flags & SCRIPT_VERIFY_DEFAULT_CHECK_TEMPLATE_VERIFY_HASH)) {
 | 
			
		||||
            if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
 | 
			
		||||
                return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (stack.size() < 1)
 | 
			
		||||
            return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
 | 
			
		||||
 | 
			
		||||
        // If the argument was not 32 bytes, treat as OP_NOP4:
 | 
			
		||||
        switch (stack.back().size()) {
 | 
			
		||||
            case 32:
 | 
			
		||||
                if (!checker.CheckDefaultCheckTemplateVerifyHash(stack.back())) {
 | 
			
		||||
                    return set_error(serror, SCRIPT_ERR_TEMPLATE_MISMATCH);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                // future upgrade can add semantics for this opcode with different length args
 | 
			
		||||
                // so discourage use when applicable
 | 
			
		||||
                if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
 | 
			
		||||
                    return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
 | 
			
		||||
                }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
A PayToBareDefaultCheckTemplateVerifyHash output matches the following template:
 | 
			
		||||
 | 
			
		||||
    bool CScript::IsPayToBareDefaultCheckTemplateVerifyHash() const
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user