美文网首页
bitcoin 通过脚本进行一段时间的资金冻结

bitcoin 通过脚本进行一段时间的资金冻结

作者: 路之遥_其漫漫_ | 来源:发表于2018-03-10 16:35 被阅读0次

    该脚本的格式

    • scriptPubKey: < expiry time > OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 < pubKeyHash > OP_EQUALVERIFY OP_CHECKSIG
    • scriptSig: < sig > < pubKey >
    • 允许一个交易的输出在未来某个时间之后才可以进行花费。即可以将资金锁定在未来的某个时间之后才可以使用。

    程序的执行

    操作码的执行

    bool EvalScript(...){
        ...
        
        case OP_CHECKLOCKTIMEVERIFY: {
            //如果脚本的检测标识 没有启用该时间锁功能;
            if (!(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) {
                // not enabled; treat as a NOP2  
                // 脚本检测标识是否也禁用该 操作码;如果是,退出报错
                if (flags &
                    SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
                    return set_error(
                        serror,
                        SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
                }
                break;
            }
            //此时栈中应至少含有1项,锁定时间
            if (stack.size() < 1) {
                return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
            }
            //将栈顶项(锁定时间)转换为可比较的 类型
            const CScriptNum nLockTime(stacktop(-1), fRequireMinimal, 5);
            //当锁定时间小于0时,退出报错
            if (nLockTime < 0) {
                return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME);
            }
            //检测该锁定时间是否合理
            if (!checker.CheckLockTime(nLockTime)) {
                return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);
            }
            break;
        }
        ...
    }
    

    上述为脚本中包含OP_CHECKLOCKTIMEVERIFY 操作码时,执行的验证过程。

    * 分别检测该功能是否启用;
    * 此时栈上的数据量,因为此时栈中应至少含有脚本的锁定时间。
    * 进行锁定时间的检测
    

    时间的检测

    bool TransactionSignatureChecker::CheckLockTime(const CScriptNum &nLockTime) const {
        // 此处为检测脚本的锁定时间应该与交易自身的时间戳在同一时间段(高度,或者时间); 
        if (!((txTo->nLockTime < LOCKTIME_THRESHOLD && nLockTime < LOCKTIME_THRESHOLD) ||
              (txTo->nLockTime >= LOCKTIME_THRESHOLD && nLockTime >= LOCKTIME_THRESHOLD))) {
            return false;
        }
        //当 脚本锁定时间大于交易时间时,标识该笔资金现在还处于冻结状态,不允许花费
        if (nLockTime > int64_t(txTo->nLockTime)) {
            return false;
        }
        //当该交易的nSequence字段为等于SEQUENCE_FINAL该值,该交易输入会被视为成熟,允许立即打包。这样就相当于绕过了脚本的时间锁定,不允许这样操做。
        //此处只检测指定的交易输入而不是所有的交易输入,是希望最大限度的减少数据量。
        if (CTxIn::SEQUENCE_FINAL == txTo->vin[nIn].nSequence) {
            return false;
        }
        //检测通过,该笔资金现在可以解冻。    
        return true;
    }
    

    上述为拿到脚本的锁定时间后进行的检测。

    * 时间锁定分为两种:一种是基于区块高度的锁定,一种是基于时间的锁定;二者通过与 LOCKTIME_THRESHOLD 进行比较来区分;
        * 当小于LOCKTIME_THRESHOLD时,即为高度;否则为时间。
    * 此时交易的时间戳应该与脚本的锁定时间处于同一 区间(高度或时间);否则无法进行比较,直接返回错误。
    * 只有当交易的时间大于等于脚本时间时,该笔资金才会解冻;否则直接返回错误。
    * 当该笔交易输入的 nSequence 字段 = SEQUENCE_FINAL该值时,相当于绕过了脚本的时间锁定,不允许这样做。
    

    操作码的描述

    OP_CHECKLOCKTIMEVERIFY : 如果栈顶项大于交易的时间戳字段,标识该交易无效,否则脚本继续执行。在以下几种情况时,同样标识脚本无效:

    * 栈为空;
    * 栈顶项为负数;
    * 栈顶项大于等于LOCKTIME_THRESHOLD(500000000);而交易的时间戳小于LOCKTIME_THRESHOLD; 反之也无效。
    * 交易输入的nSequence等于SEQUENCE_FINAL(0xffffffff).
    

    OP_DROP : 移除栈顶项;

    脚本的执行

    未命名文件.png

    本文由 Copernicus团队 姚永芯写作,转载无需授权。

    相关文章

      网友评论

          本文标题:bitcoin 通过脚本进行一段时间的资金冻结

          本文链接:https://www.haomeiwen.com/subject/lgkbfftx.html