从 sCrypt 智能合约中访问区块链数据

Posted freedomhero

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从 sCrypt 智能合约中访问区块链数据相关的知识,希望对你有一定的参考价值。

上一篇文章中,我们介绍了一种以最小信任访问块和其中的交易的方法。
本文中, 我们将其扩展为在包含多个区块。使用该技术,我们基于区块时间开发了一个简单的投注合约。我们还展示了另一种阻止伪造块的方法。

一个由 3 个区块组成的序列

多个区块组成的序列

如下所示,isBlockHeaderValid() 验证一个区块序列,而不是我们在上一篇文章中所做的单个区块。我们在第 8 行重用现有代码中的函数 isBlockHeaderValid() 来验证每个单独的块。此外,我们在第 12 行对区块头进行哈希处理,并确保哈希与第 14 行的下一个区块头中的 prevBlockHash 字段匹配。

// is a chain of block headers valid
static function isBlockHeaderChainValid(static const int N, BlockHeader[N] headers, int blockchainTarget) : bool 
    bool res = true;

    loop (N) : i 
        if (res) 
            // each block is valid
            if (!isBlockHeaderValid(headers[i], blockchainTarget))
                res = false;

            if (i > 0) 
                Sha256 prevBlockHash = blockHeaderHash(headers[i - 1]);
                // blocks are chained
                if (prevBlockHash != headers[i].prevBlockHash)
                    res = false; 
            
        
    

    return res;

Blockchain 源代码

也就是说,验证了这两个块是链接在一起的。

案例研究:押注出块时间

平均而言,在比特币上产生一个区块需要 10 分钟。Alice 和 Bob 想打赌挖掘特定区块需要多长时间。他们每个人都在一个包含了以下智能合约的交易中锁定了一些 BSV。交易广播后,将被处理打包进一个区块。如果该区块的产生时间少于 10 分钟,则 Alice 获胜并拿走所有锁定的 BSV;否则,鲍勃获胜。我们使用块的时间戳(标头中的第 4 个字段)与其前一个块的时间戳之间的差异作为出块时间¹。

// bet on block time: how long it takes to mine the block containing the bet transaction
contract BlockTimeBet 
    // only 2 is needed; 7 means the transaction has 6 confirmations
    static const int N = 7;
    // 10 minutes in seconds
    static const int AVG_BLOCK_TIME = 600;
    // maximal target for any block to be considered valid
    int blockchainTarget;

    PubKey alice;
    PubKey bob;


    // header[1] is the block containing the contract tx
    public function main(BlockHeader[N] headers, MerkleProof merkleproof, Sig sig,  SigHashPreimage txPreimage) 
        require(Tx.checkPreimage(txPreimage));

        // get id of previous tx
        Sha256 prevTxid = Sha256(SigHash.outpoint(txPreimage)[:32]);

        // validate a chain of block headers
        require(Blockchain.isBlockHeaderChainValid(N, headers, this.blockchainTarget));

        // verify previous tx is in block with index 1
        require(Blockchain.txInBlock(prevTxid, headers[1], merkleproof));

        // block time is the time difference between this block and last
        int blockTime = headers[1].time - headers[0].time;

        // Alice wins if block is mined within 10 mins; otherwise Bob wins
        PubKey winner = blockTime < AVG_BLOCK_TIME ? this.alice : this.bob;
        require(checkSig(sig, winner));
    

BlockTimeBet 合约源代码

与上一篇文章的 BlockchainPRNG 合约一样,我们使用 OP_PUSH_TX 技术 来获取包含投注合约的交易的 txid 。第 20 行验证区块头链是否合法,第 23 行验证投注交易在其中。第 26 行计算出块时间,用于在第 29 行确定获胜者。

鉴别假块

在上一篇文章中,我们引入了 blockchainTarget 参数来控制可接受的区块头的难度。我们还可以要求在一个区块之上构建多个区块,从而使导入假的区块数据变得更加困难。要求的区块越多,伪造它的成本就越高。这类似于使用比特币购买商品时所需的 6 次确认。在上面的投注合约中,我们只需要将 N 改为 7 即可确保包含该合约的交易有 6 个确认。

附录

[1]: 比特币区块时间戳不精确,通常不能用于衡量 10 分钟的时间间隔。但只要它是随机且难以预测的,投注合约就可以,因为它依赖于区块时间的随机性,而不是其精度。

以上是关于从 sCrypt 智能合约中访问区块链数据的主要内容,如果未能解决你的问题,请参考以下文章

从 sCrypt 智能合约中访问区块链数据

从 sCrypt 智能合约中访问区块链数据

从 sCrypt 智能合约中访问区块链数据

Solidity -> sCrypt 转译器简介

官方发布|BSV区块链协会推出全新智能合约转译器

如何在 sCrypt 合约中实现浮点数运算