Bitcoin SV 和 Bitcoin Core 之间首次跨链原子交换

我们已经执行了 Bitcoin SV 和 Bitcoin Core 之间的首次原子交换。 这一成就代表了比特币 SV 的重大进步,以去信任的方式促进了与其他区块链的无缝互操作性。

图片源自Gemini

图片源自Gemini

在上一篇文章中,我们解释了原子交换的高级理论。 我们深入研究了使用哈希时间锁定合约(HTLC)在 BSV 和 BTC 之间进行原子交换的实际示例。 让我们将此过程分解为四个基本步骤,每个步骤都包含您可以自己运行的代码片段。

第 1 步:Alice 在 BTC 上发起交易

该过程从 Alice 开始,她选择一个随机整数 x 并使用 SHA-256 算法创建一个哈希值 (xHash)。 接下来,Alice 部署了一个 Pay-to-Witness-Script-Hash (P2WSH) 交易,其中包括她想要与 Bob 交易的 BTC 数量。

我们使用 bitcoinutils 库构建 Alice 的交易:

def main():
    # always remember to setup the network
    setup('testnet')

    # TODO: remember to adjust the values marked by "TODO" to your use case.
    alicePriv = PrivateKey('TODO')
    alicePub = alicePriv.get_public_key()
    bobPub = PublicKey('TODO')
    txid = 'TODO'  # Previous transaction ID
    vout = 2  # Previous transaction ouput index
    amount = 0.00001850   # Amount in output
    fee = 0.00000125      # Fee in new transaction
    x = 'f00cfd8df5f92d5e94d1ecbd9b427afd14e03f8a3292ca4128cd59ef7b9643bc'
    xHash = '1908c59a71781b7a44182ec39dd84a8a9e13dc31691fead8631730f5f5ab7b65'
    nBlocksLocked = '06'  # 6 blocks ~ 1 hr

    # HTLC script:
    htlc_redeem_script = Script(
        ['OP_IF',
            'OP_SHA256',
            xHash,
            'OP_EQUALVERIFY',
            bobPub.to_hex(),
            'OP_CHECKSIG',
        'OP_ELSE',
            nBlocksLocked,
            'OP_CHECKSEQUENCEVERIFY',
            'OP_DROP',
            alicePriv.get_public_key().to_hex(),
            'OP_CHECKSIG',
        'OP_ENDIF']
    )
    toAddress = P2wshAddress.from_script(htlc_redeem_script)

    # Create transaction input from tx id of utxo.
    txIn = TxInput(txid, vout)
    redeem_script1 = Script(
        ['OP_DUP', 'OP_HASH160', alicePub.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG'])

    # Create transaction output, which contains the P2WSH for the HTLC script.
    txOut = TxOutput(to_satoshis(amount - fee), toAddress.to_script_pub_key())

    # Create transaction.
    tx = Transaction([txIn], [txOut], has_segwit=True)

    # Sign transaction.
    sig1 = alicePriv.sign_segwit_input(tx, 0, redeem_script1, to_satoshis(amount))
    tx.witnesses.append(Script([sig1, alicePub.to_hex()]))

    # Print raw signed transaction ready to be broadcast.
    print("\nRaw signed transaction:\n" + tx.serialize())
    print("\nTxId:", tx.get_txid())

执行后,代码将打印原始的序列化交易,我们可以使用 Blockstream 的区块浏览器将其广播到 BTC 网络。

该 P2WSH 交易脚本由条件子句组成,这些条件子句包括需要 Bob 的公钥和秘密 x,或者 Alice 的签名和花费交易的时间延迟。

Bob 在 BTC 上进行应答

作为回应,Bob 在 BSV 区块链上部署了等效的 sCrypt 智能合约,其中包含他准备与 Alice 交换的 BSV 金额。

class HashTimeLockContract extends SmartContract {
    @prop() readonly alicePubKey: PubKey

    @prop() readonly bobPubKey: PubKey

    @prop() readonly hashX: Sha256

    @prop() readonly timeout: bigint // Can be a timestamp or block height.


    // hash lock
    @method()
    public unlock(x: ByteString, aliceSig: Sig) {
        // Check if H(x) == this.hashX
        assert(sha256(x) == this.hashX, 'Invalid secret.')

        // Verify Alices signature.
        assert(this.checkSig(aliceSig, this.alicePubKey))
    }

    // time lock
    @method()
    public cancel(bobSig: Sig) {
        assert(this.ctx.locktime >= this.timeout, 'locktime has not yet expired')

        // Verify Bobs signature.
        assert(this.checkSig(bobSig, this.bobPubKey))
    }
}

Bob 获得了 x 的哈希值,但不是 x 本身,以及 Alice 的公钥。 然后,他使用以下部署代码部署智能合约:


const alicePubKey = bsv.PublicKey.fromHex('TODO')

const bobPrivKey = bsv.PrivateKey.fromWIF('TODO')
const bobPubKey = bobPrivKey.publicKey

const amount = 100000  // TODO: amount of BSV to be locked in the contract

const xHash = toByteString(
    '1908c59a71781b7a44182ec39dd84a8a9e13dc31691fead8631730f5f5ab7b65'
)
const lockTimeMin = 1688715000 // Timestamp, after which Bob can withdraw his funds.

await CrossChainSwap.compile()

// Connect Bob signer.
const provider = new DefaultProvider(bsv.Networks.testnet)
const signer = new TestWallet(bobPrivKey, provider)

const crossChainSwap = new CrossChainSwap(
    PubKey(alicePubKey.toHex()),
    PubKey(bobPubKey.toHex()),
    xHash,
    BigInt(lockTimeMin)
)
await crossChainSwap.connect(signer)


// Contract deployment.
const deployTx = await crossChainSwap.deploy(amount)
console.log('CrossChainSwap contract deployed: ', deployTx.id)

第三步:Alice 解锁 Bob 的合约

成功部署 sCrypt 合约后,Alice 现在可以通过泄露秘密 x 来调用 Bob 合约的公共方法 unlock()。 结果,Alice 拥有了 Bob 的 BSV。

const deployedContractTXID = 'TODO'
const x = toByteString('f00cfd8df5f92d5e94d1ecbd9b427afd14e03f8a3292ca4128cd59ef7b9643bc')

// Alice unlocks contract and takes the funds.
const provider = new DefaultProvider(bsv.Networks.testnet)
const signer = new TestWallet(alicePrivKey, provider)

const tx = await signer.provider.getTransaction(deployedContractTXID)
const crossChainSwap = CrossChainSwap.fromTx(tx, 0)
await crossChainSwap.connect(signer)

const { tx: callTx, atInputIndex } =
    await crossChainSwap.methods.unlock(
        x,
        (sigResps) => findSig(sigResps, alicePubKey),
        {
            pubKeyOrAddrToSign: alicePubKey,
        } as MethodCallOptions<CrossChainSwap>
    )
console.log('CrossChainSwap "unlock" method called: ', callTx.id)

第四步:Bob 取回 Alice 的 BTC

一旦 Alice 透露了 x,Bob 就可以用它来解锁 BTC 区块链上的 P2WSH UTXO。 这个过程允许鲍勃索取爱丽丝的比特币,从而完成原子交换。

def main():
    # always remember to setup the network
    setup('testnet')

    # TODO: Set values:
    bobPriv = PrivateKey('TODO')
    bobPub = bobPriv.get_public_key()
    alicePub = PublicKey('TODO')
    txid = 'TODO'  # Previous transaction ID
    vout = 0 # Previous transaction ouput index
    amount = 0.00001725   # Amount in output
    fee = 0.00000125      # Fee in new transaction
    x = 'f00cfd8df5f92d5e94d1ecbd9b427afd14e03f8a3292ca4128cd59ef7b9643bc'
    xHash = '1908c59a71781b7a44182ec39dd84a8a9e13dc31691fead8631730f5f5ab7b65'
    nBlocksLocked = '06'  # 6 blocks ~ 1 hr
    toAddress = P2wpkhAddress.from_address('TODO')

    # HTLC Script:
    htlc_redeem_script = Script(
        ['OP_IF',
            'OP_SHA256',
            xHash,
            'OP_EQUALVERIFY',
            bobPub.to_hex(),
            'OP_CHECKSIG',
        'OP_ELSE',
            nBlocksLocked,
            'OP_CHECKSEQUENCEVERIFY',
            'OP_DROP',
            alicePub.to_hex(),
            'OP_CHECKSIG',
        'OP_ENDIF']
    )

    fromAddress = P2wshAddress.from_script(htlc_redeem_script)

    # Create transaction input from tx id of UTXO
    txin = TxInput(txid, vout)

    txOut1 = TxOutput(to_satoshis(amount - fee), toAddress.to_script_pub_key())

    tx = Transaction([txin], [txOut1], has_segwit=True)

    # NOTE: In P2WSH, the argument for OP_IF and OP_NOTIF MUST be exactly an empty vector or 0x01, or the script evaluation fails immediately.

    # Normal unlock:
    sig1 = bobPriv.sign_segwit_input(tx, 0, htlc_redeem_script, to_satoshis(amount))
    tx.witnesses.append(Script([
        sig1,
        x,
        '01',  # OP_TRUE
        htlc_redeem_script.to_hex()]))

    # print raw signed transaction ready to be broadcasted
    print("\nRaw signed transaction:\n" + tx.serialize())
    print("\nTxId:", tx.get_txid())

我们可以广播打印的原始交易并完成交换。

争议解决

在发生争议的情况下,Alice 和 Bob 都可以在一段时间后提取资金。

此功能提供了一种故障安全机制,可确保在交换不成功或有争议的情况下不会永久锁定资金。 时间限制为双方解锁各自的合同提供了足够的窗口。

在爱丽丝的例子中,我们可以修改见证人的构造:

# ...

# Create transaction input from tx id of UTXO.
txin = TxInput(txid, vout, sequence=bytes.fromhex('FFFFFFFE'))

# ...

locktime = bytes.fromhex('64A7F990') # 1688730000
tx = Transaction([txin], [txOut1], has_segwit=True, locktime=locktime)

# Withdrawal:
sig1 = alicePriv.sign_segwit_input(tx, 0, htlc_redeem_script, to_satoshis(amount))
tx.witnesses.append(Script([
    sig1,
    '', # OP_FALSE
    htlc_redeem_script.to_hex()]))

#...

传递 OP_FALSE 作为第一个输入将在 OP_ELSE 之后执行脚本,这会检查时间锁定是否已过期。

同样,在 Bob 的情况下,我们修改代码以调用 cancel 方法:


// Bob withdraws after timeout passed.
const { tx: callTx, atInputIndex } =
    await crossChainSwap.methods.cancel(
        (sigResps) => findSig(sigResps, bobPubKey),
        {
            lockTime: 1688730000,
            pubKeyOrAddrToSign: bobPubKey,
        } as MethodCallOptions<CrossChainSwap>
    )
console.log('CrossChainSwap "cancel" method called: ', callTx.id)

首次成功跨链BTC-BSV互换

我们在 BSV 和 BTC 主网之间进行了首次成功的原子交换。

  • BTC 上的初始 P2WSH 交易:af7a8c31e489c18d6fe46141cf2cbc777aeb23672679eb199bde4813d6fe41d4

  • BSV 上等效的 sCrypt 智能合约交易:8598d203e8bdd45b7025e334cdebdef06be88381dec245d95108e658e8373f9c

  • Alice 调用 unlock 方法:68c2c5a91645112df6b62a5ee6ea9e0e22f29499b88c9ccffc23f8f86ec63d09

  • 鲍勃解锁了 BTC:9c697bf8f0d2c11285cfab3a2b8a856a1c18ae048d481c7bb3f93f9ccd2dbaad

这也是一个未完成的交换示例。 爱丽丝和鲍勃都收回了他们的资金。

  • BTC: 395dde14e489208302c1d6ac3b4fc0db890c000fd79f3e836fc74043a54480ff
  • BSV: 12e701237a1f6da2b69f1d4dab2b1208d3f6003f7b45ef178c5c7d9e00c54273

本文中显示的所有代码都可以在我们的 GitHub 上找到。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/194073.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[设计模式] 常见的设计模式

文章目录 设计模式的 6 大设计原则设计模式的三大分类常见的设计模式有哪几种1. 单例模式&#xff1a;保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点。&#xff08;连接池&#xff09;1. 饿汉式2. 懒汉式3. 双重检测 2. 工厂模式3. 观察者模式● 推模型● 拉…

Apache Doris 整合 FLINK 、 Hudi 构建湖仓一体的联邦查询入门

1.概览 多源数据目录&#xff08;Multi-Catalog&#xff09;功能&#xff0c;旨在能够更方便对接外部数据目录&#xff0c;以增强Doris的数据湖分析和联邦数据查询能力。 在之前的 Doris 版本中&#xff0c;用户数据只有两个层级&#xff1a;Database 和 Table。当我们需要连…

嵌入式八股 | 笔试面试 | 校招秋招 | 详细讲解

〇、前言 作者&#xff1a;赛博二哈 本嵌入式八股撰写初衷&#xff1a;当时求职翻遍了我能找到的所有八股&#xff0c;不论是嵌入式的&#xff0c;计算机基础的&#xff0c;C艹的&#xff0c;都很难看下去&#xff0c;细究其原因&#xff0c;有个最大的痛点&#xff1a; 大部…

Python读取Ansible playbooks返回信息

一&#xff0e;背景及概要设计 当公司管理维护的服务器到达一定规模后&#xff0c;就必然借助远程自动化运维工具&#xff0c;而ansible是其中备选之一。Ansible基于Python开发&#xff0c;集合了众多运维工具&#xff08;puppet、chef、func、fabric&#xff09;的优点&#x…

使用opencv的matchTemplate进行银行卡卡号识别

![字体文件](https://img-blog.csdnimg.cn/3a16c87cf4d34aceb0778c4b20ddadb2.png#pic_center import cv2 import numpy as npdef show_img(img, name"temp"):img cv2.resize(img, (0, 0), fx3, fy3)cv2.imshow(name, img)cv2.waitKey(0)cv2.destroyAllWindows()de…

242. 有效的字母异位词

这篇文章会收录到 :算法通关村第十二关-白银挑战字符串经典题目-CSDN博客 242. 有效的字母异位词 描述 : 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的字母异位词。 注意&#xff1a;若 s 和 t 中每个字符出现的次数都相同&#xff0c;则称 s 和 t …

VsCode 调试 MySQL 源码

1. 启动 MySQL 2. 查看 MySQL 进程号 [root ~]# ps -ef | grep mysqld root 21479 1 0 Nov01 ? 00:00:00 /bin/sh /usr/local/mysql/bin/mysqld_safe --datadir/usr/local/mysql/data --pid-file/usr/local/mysql/data/mysqld.pid root 26622 21479 0 …

【JDK21】详解虚拟线程

目录 1.概述 2.虚拟线程是为了解决哪些问题 2.1.线程切换的巨大代价 2.2.哪些情况会造成线程的切换 2.3.线程资源是有限的 3.虚拟线程 4.适用场景 1.概述 你发任你发&#xff0c;我用JAVA8&#xff1f;JDK21可能要对这句话say no了。 现在Oracle JDK是每4个版本&#x…

minio分布式存储系统

目录 拉取docker镜像 minio所需要的依赖 文件存放的位置 手动上传文件到minio中 工具类上传 yml配置 config类 service类 启动类 测试类 图片 视频 删除minio服务器的文件 下载minio服务器的文件 拉取docker镜像 拉取稳定版本:docker pull minio/minio:RELEASE.20…

FLASK博客系列6——数据库之谜

我们上一篇已经实现了简易博客界面&#xff0c;你还记得我们的博客数据是自己手动写的吗&#xff1f;但实际应用中&#xff0c;我们是不可能这样做的。大部分程序都需要保存数据&#xff0c;所以不可避免要使用数据库。我们这里为了简单方便快捷&#xff0c;使用了超级经典的SQ…

MySOL常见四种连接查询

1、内联接 &#xff08;典型的联接运算&#xff0c;使用像 或 <> 之类的比较运算符&#xff09;。包括相等联接和自然联接。 内联接使用比较运算符根据每个表共有的列的值匹配两个表中的行。例如&#xff0c;检索 students和courses表中学生标识号相同的所有行。 2、…

linux下的工具---vim

一、了解vim 1、vim是linux的开发工具 2、vi/vim的区别简单点来说&#xff0c;它们都是多模式编辑器&#xff0c;不同的是vim是vi的升级版本&#xff0c;它不仅兼容vi的所有指令&#xff0c;而且还有一些新的特性在里面。例如语法加亮&#xff0c;可视化操作不仅可以在终端运行…

前端OFD文件预览(vue案例cafe-ofd)

0、提示 下面只有vue的使用示例demo &#xff0c;官文档参考 cafe-ofd - npm 其他平台可以参考 ofd - npm 官方线上demo: ofd 1、安装包 npm install cafe-ofd --save 2、引入 import cafeOfd from cafe-ofd import cafe-ofd/package/index.css Vue.use(cafeOfd) 3、使…

计算机服务器中了mallox勒索病毒如何处理,mallox勒索病毒解密文件恢复

科技技术的发展推动了企业的生产运营&#xff0c;网络技术的不断应用&#xff0c;极大地方便了企业日常生产生活&#xff0c;但网络毕竟是一把双刃剑&#xff0c;网络安全威胁一直存在&#xff0c;近期&#xff0c;云天数据恢复中心接到很多企业的求助&#xff0c;企业的计算机…

文件夹重命名技巧:如何整理过长且混乱的文件夹名称

当浏览计算机文件夹时&#xff0c;有时候会遇到一些过长且混乱的文件夹名称&#xff0c;给文件夹管理带来不便。倘若手动修改文件夹名称会出现错误的机率过大&#xff0c;且这样操作太耗费时间和精力。有什么方法能够避免手动修改文件夹名称&#xff0c;提升工作效率的方法呢&a…

万字详解,和你用RAG+LangChain实现chatpdf

像chatgpt这样的大语言模型(LLM)可以回答很多类型的问题,但是,如果只依赖LLM,它只知道训练过的内容,不知道你的私有数据:如公司内部没有联网的企业文档,或者在LLM训练完成后新产生的数据。(即使是最新的GPT-4 Turbo,训练的数据集也只更新到2023年4月)所以,如果我们…

leetCode 841. 钥匙和房间 图遍历 深度优先遍历+广度优先遍历 + 图解

841. 钥匙和房间 - 力扣&#xff08;LeetCode&#xff09; 有 n 个房间&#xff0c;房间按从 0 到 n - 1 编号。最初&#xff0c;除 0 号房间外的其余所有房间都被锁住。你的目标是进入所有的房间。然而&#xff0c;你不能在没有获得钥匙的时候进入锁住的房间。当你进入一个房…

Android 12 打开网络ADB并禁用USB连接ADB

平台 RK3588 Android 12 Android 调试桥 (adb) Android 调试桥 (adb) 是一种功能多样的命令行工具&#xff0c;可让您与设备进行通信。adb 命令可用于执行各种设备操作&#xff0c;例如安装和调试应用。adb 提供对 Unix shell&#xff08;可用来在设备上运行各种命令&am…

保护IP地址不被窃取的几种方法

随着互联网的普及和信息技术的不断发展&#xff0c;网络安全问题日益凸显。其中&#xff0c;保护个人IP地址不被窃取成为了一个重要的问题。IP地址是我们在互联网上的身份标识&#xff0c;如果被他人获取&#xff0c;就可能导致个人隐私泄露、计算机受到攻击等一系列问题。因此…

笔记62:注意力汇聚 --- Nadaraya_Watson 核回归

本地笔记地址&#xff1a;D:\work_file\&#xff08;4&#xff09;DeepLearning_Learning\03_个人笔记\3.循环神经网络\第10章&#xff1a;动手学深度学习~注意力机制 a a a a a a a a a a a a a a a a