Skip to content

Clone

State-continuation clone verifier.

txt
# Verify that the spend creates a new output with the same value and script identity.
Contract Clone:

    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)

        pre_value = pretx.Outputs[vout_copy].Value.Clone()
        SetAlt(pre_value)

        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)

        # Rebuild the previous outputs exactly as they were hashed into the prior txid.
        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)

        # The output digest is joined with the unlocking-script digest.
        SetMain(tx_data)
        tx_data = Sha256(tx_data)
        tx_data = Cat(pretx.UnlockingScriptHash, tx_data)
        SetAlt(tx_data)
        # Add the input digest and header bytes to finish rebuilding the txid preimage.
        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)
        # The rebuilt txid must be the outpoint referenced by this spend.
        txid = Hash256(tx_data)
        preTXID = BVM.unlockingInput.Slice(0, 32)
        EqualVerify(txid, preTXID)

    def verifyCurrentTX(ctx: CurrentTX):
        # While hashing current outputs, look for at least one matching continuation.
        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:
                    # Size narrows the candidate; script partial hash and value confirm it.
                    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)
                    ctx_value = ctx.Outputs[i].Value.Clone()
                    SetMain(pre_value)
                    pre_value_copy = pre_value.Clone()
                    EqualVerify(pre_value_copy, ctx_value)
                    SetAlt(pre_value)
                    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)