Skip to content

Counter

只递增延续的有状态计数器。

txt
# 读取上一轮计数状态,并要求下一轮状态只能加一。
Contract Counter:

    Struct Script:
        SuffixData: string
        PartialHash: string
        Size: number

    Struct Output:
        Value: number
        LockingScript: Script

    Struct Input:
        Data: {txid: hex32, vout: hex4, sequence: hex4}

    Struct PreTX:
        VLIO: string
        Inputs: Input[3]
        UnlockingScriptHash: string
        Outputs: Output[3]

    Struct CurrentTX:
        Outputs: Output[3]

    def getCountFromPreTX(pretx: PreTX):
        utxoData: {txid: hex32, vout: hex4, sequence: hex4}
        utxoData = Push(BVM.unlockingInput)
        vout = BinToNum(utxoData.vout)
        vout_copy = vout.Clone()
        Delete(utxoData.sequence)
        Delete(utxoData.txid)

        code_data = pretx.Outputs[vout_copy].LockingScript.SuffixData.Clone()
        pre_count = BinToNum(code_data.Slice(1, 8))
        SetAlt(pre_count)

        vout_copy = vout.Clone()
        pre_code_partialhash = pretx.Outputs[vout_copy].LockingScript.PartialHash.Clone()
        SetAlt(pre_code_partialhash)
        pre_code_size = pretx.Outputs[vout_copy].LockingScript.Size.Clone()
        SetAlt(pre_code_size)

        # 按上一笔交易的哈希方式重新拼出全部输出。
        tx_data = Push(0)
        SetAlt(tx_data)
        for i in Range(2, -1, -1):
            size_copy = pretx.Outputs[i].LockingScript.Size.Clone()
            if size_copy != 0:
                tx_data_temp = PartialHash(pretx.Outputs[i].LockingScript.SuffixData, pretx.Outputs[i].LockingScript.PartialHash, pretx.Outputs[i].LockingScript.Size)
                tx_data_temp = Cat(pretx.Outputs[i].Value, tx_data_temp)
                SetMain(tx_data)
                tx_data = Cat(tx_data_temp, tx_data)
                SetAlt(tx_data)
                Keep(tx_data)
            else:
                Delete(pretx.Outputs[i].LockingScript.Size)
                Delete(pretx.Outputs[i].LockingScript.PartialHash)
                Delete(pretx.Outputs[i].LockingScript.SuffixData)
                Delete(pretx.Outputs[i].Value)

        # 输出摘要还需要与解锁脚本摘要拼接。
        SetMain(tx_data)
        tx_data = Sha256(tx_data)
        tx_data = Cat(pretx.UnlockingScriptHash, tx_data)
        SetAlt(tx_data)
        # 继续加入输入摘要和头部字节,完成 txid 原像重建。
        tx_input_data = Push(0)
        for i in Range(2, -1, -1):
            tx_input_data = Cat(pretx.Inputs[i].Data, tx_input_data)
        tx_input_hash = Sha256(tx_input_data)
        SetMain(tx_data)
        tx_data = Cat(tx_input_hash, tx_data)
        tx_data = Cat(pretx.VLIO, tx_data)
        # 重建出的 txid 必须等于当前花费引用的 outpoint。
        txid = Hash256(tx_data)
        preTXID = BVM.unlockingInput.Slice(0, 32)
        EqualVerify(txid, preTXID)

    def verifyCurrentTX(ctx: CurrentTX):
        # 找到延续输出,并确认其中的计数字节比上一轮大一。
        time = Push(3)
        SetAlt(time)
        outputs_data = Push(0)
        SetAlt(outputs_data)
        for i in Range(2, -1, -1):
            size = ctx.Outputs[i].LockingScript.Size.Clone()
            size_copy = size.Clone()
            if size_copy != 0:
                SetMain(outputs_data)
                SetMain(time)
                SetMain(pre_code_size)
                pre_code_size_copy = pre_code_size.Clone()
                if size == pre_code_size_copy:
                    # 有效延续必须保持相同的脚本标识。
                    SetMain(pre_code_partialhash)
                    pre_code_partialhash_copy = pre_code_partialhash.Clone()
                    code_partialhash = ctx.Outputs[i].LockingScript.PartialHash.Clone()
                    EqualVerify(pre_code_partialhash_copy, code_partialhash)
                    code_suffixdata = ctx.Outputs[i].LockingScript.SuffixData.Clone()
                    ctx_count = BinToNum(code_suffixdata.Slice(1, 8))
                    SetMain(pre_count)
                    pre_count_copy = pre_count.Clone()
                    EqualVerify(pre_count_copy + 1, ctx_count)
                    SetAlt(pre_count)
                    SetAlt(pre_code_partialhash)
                    time = time - 1
                    SetAlt(pre_code_size)
                    SetAlt(time)
                    Keep(time)
                else:
                    SetAlt(pre_code_size)
                    SetAlt(time)
                SetAlt(outputs_data)
                outputs_data_temp = PartialHash(ctx.Outputs[i].LockingScript.SuffixData, ctx.Outputs[i].LockingScript.PartialHash, ctx.Outputs[i].LockingScript.Size)
                outputs_data_temp = Cat(ctx.Outputs[i].Value, outputs_data_temp)
                SetMain(outputs_data)
                outputs_data = Cat(outputs_data_temp, outputs_data)
                SetAlt(outputs_data)
                Keep(outputs_data)
            else:
                Delete(size)
                Delete(ctx.Outputs[i].LockingScript.Size)
                Delete(ctx.Outputs[i].LockingScript.PartialHash)
                Delete(ctx.Outputs[i].LockingScript.SuffixData)
                Delete(ctx.Outputs[i].Value)
        SetMain(outputs_data)
        outputs_data = Sha256(outputs_data)
        EqualVerify(outputs_data, BVM.outputsHash)
        SetMain(time)
        Return (time < 3 == 1)
        Push(0x0100000000000000)