没有哈希时间锁定合约的跨链原子交换

在上一篇文章中,我们介绍了使用哈希时间锁定合约(HTLC)的跨链原子交换实现。 今天,我们介绍一种无需 HTLC 即可实现的替代方法。 这将原子交换扩展到缺乏哈希锁和时间锁的区块链。

使用 SPV 证明交易已被挖掘

让我们按照商定的价格将 Alice 的 BTC 币与 Bob 的 BSV 币进行交换。

在这篇文章中,我们展示了 BSV 智能合约能够验证区块链中包含的交易。 重要的是,这是在不依赖外部预言机的情况下实现的。 基本思想是使用工作难度证明来验证区块头。 使用 Merkle 证明,我们可以验证该区块中是否包含交易,类似于链下完成的 SPV。

图片源于BSV Academy

这意味着 BSV 上的智能合约可以编程为根据 BTC 等区块链上特定交易的确认来执行特定操作。

在原子交换的背景下,智能合约本质上是这样说的:

“如果您将X BTC发送到Y地址,您就可以获得该合约中当前持有的BSV资产。”

该功能之所以成为可能,是因为 BSV 合约能够验证特定交易是否已在 BTC 区块链上成功开采。 合约可以对特定的BTC交易进行验证,确保预期的BTC金额已发送到正确的地址。

为了发起报价,Bob 在智能合约中确保 BSV 币的安全,并指定接收 BTC 所需的地址。 一旦 Alice 发送了 BTC,她就可以领取合约中锁定的 BSV。 此过程不涉及任何受信任的中介机构。

完整的协议序列

BSV 和 BTC 之间的原子交换协议可以按照以下步骤执行。

  1. 合约部署:Bob 在 BSV 链上部署智能合约。 该合约持有 Bob 打算与 Alice 交换的 BSV 资金。 该合同还包含故障安全时间锁。

  2. 付款和证明:Alice 将约定数量的 BTC 在 BTC 链上发送给 Bob。 在该交易被开采到区块中后,她获得了该交易的 Merkle 证明。 请注意,这是一个简单的支付交易,没有 HLTC。

  3. 验证和解锁:Alice 将 Merkle 证明提交给 BSV 合约。 合约验证证明并确认将 Alice 的 BTC 交易包含给 Bob。 如果证明得到验证,Alice 就可以解锁并领取合约中的 BSV 资金。

如果Bob没有及时收到付款,他可以在时间锁定到期后取回他的币。

请注意,智能合约是在 BTC 付款广播之前部署的。 这样,Alice 就能保证在向 Bob 付款后,她会收到正确金额的 BSV。 该锁定时间还必须足够长,以便支付交易能够在 BTC 上进行挖掘。

通过稍加修改,Alice 在 Bob 合约部署时甚至可以是未知的。 Bob 的报价是公开的,任何人向他支付适量的 BTC 都可以解锁他锁定的 BSV。

与基于 HTLC 的原子交换相比

这种方法的一个关键优点是,即使对于没有哈希锁或时间锁的区块链,它也可以实现原子交换。 只要有一种机制可以不信任地证明其中包含交易(例如,使用 Merkle 证明),则具有智能合约功能来验证该证明的其他链就可以与其进行交换。

实现

在 BSV 中,智能合约可以在 sCrypt 中实现,如下所示。

export type VarIntRes = {val: bigintnewIdx: bigint
}class CrossChainSwap2 extends SmartContract {static readonly LOCKTIME_BLOCK_HEIGHT_MARKER = 500000000static readonly UINT_MAX = 0xffffffffnstatic readonly MIN_CONF = 3static readonly BTC_MAX_INPUTS = 3@prop()readonly aliceAddr: PubKeyHash@prop()readonly bobAddr: PubKeyHash@prop()readonly bobP2WPKHAddr: PubKeyHash@prop()readonly timeout: bigint // Can be a timestamp or block height.@prop()readonly targetDifficulty: bigint@prop()readonly amountBTC: bigint@prop()readonly amountBSV: bigint// ...@method()checkBtcTx(btcTx: ByteString): void {// Most things should be the same as in BSV except the witness data and flag.// - Check (first) output is P2WPKH to Bobs public key.// - Check (first) output amount is equal to this.amountBTClet idx = 4n// Make sure to serialize BTC tx without witness data.// See https://github.com/karask/python-bitcoin-utils/blob/a41c7a1e546985b759e6eb2ae4524f466be809ca/bitcoinutils/transactions.py#L913assert(slice(btcTx, idx, idx + 2n) != toByteString('0001'),'Witness data present. Please serialize without witness data.') INPUTS:const inLen = CrossChainSwap2.parseVarInt(btcTx, idx)assert(inLen.val <= BigInt(CrossChainSwap2.BTC_MAX_INPUTS),'Number of inputs too large.')idx = inLen.newIdxfor (let i = 0n; i < CrossChainSwap2.BTC_MAX_INPUTS; i++) {if (i < inLen.val) {//const prevTxID = slice(btcTx, idx, idx + 32n)idx += 32n//const outIdx = slice(btcTx, idx, idx + 4n)idx += 4nconst scriptLen = CrossChainSwap2.parseVarInt(btcTx, idx)idx = scriptLen.newIdxidx += scriptLen.val//const nSequence = slice(btcTx, idx, idx + 4n)idx += 4n}} FIRST OUTPUT:// Check if (first) output pays Bob the right amount and terminate and set res to true.const outLen = CrossChainSwap2.parseVarInt(btcTx, idx)idx = outLen.newIdxconst amount = Utils.fromLEUnsigned(slice(btcTx, idx, idx + 8n))assert(amount == this.amountBTC, 'Invalid BTC output amount.')idx += 8nconst scriptLen = CrossChainSwap2.parseVarInt(btcTx, idx)idx = scriptLen.newIdxconst script = slice(btcTx, idx, idx + scriptLen.val)assert(len(script) == 22n, 'Invalid locking script length.')assert(script == toByteString('0014') + this.bobP2WPKHAddr,'Invalid locking script.')// Data past this point is not relevant in our use-case.}@method()public swap(btcTx: ByteString,merkleProof: MerkleProof,headers: FixedArray<BlockHeader, typeof CrossChainSwap2.MIN_CONF>,alicePubKey: PubKey,aliceSig: Sig) {// Check btc tx.this.checkBtcTx(btcTx)// Calc merkle root.const txID = hash256(btcTx)const merkleRoot = MerklePath.calcMerkleRoot(txID, merkleProof)// Check if merkle root is included in the first BH.assert(merkleRoot == headers[0].merkleRoot,"Merkle root of proof doesn't match the one in the BH.")// Check target diff for headers.for (let i = 0; i < CrossChainSwap2.MIN_CONF; i++) {assert(Blockchain.isValidBlockHeader(headers[i],this.targetDifficulty),`${i}-nth BH doesn't meet target difficulty`)}// Check header chain.let h = Blockchain.blockHeaderHash(headers[0])for (let i = 0; i < CrossChainSwap2.MIN_CONF; i++) {if (i >= 1n) {const header = headers[i]// Check if prev block hash matches.assert(header.prevBlockHash == h,`${i}-th BH wrong prevBlockHash`)// Update header hash.h = Blockchain.blockHeaderHash(header)}}// Verify Alices signature.assert(hash160(alicePubKey) == this.aliceAddr, 'Alice wrong pub key.')assert(this.checkSig(aliceSig, alicePubKey))}@method()public cancel(bobPubKey: PubKey, bobSig: Sig) {// Ensure nSequence is less than UINT_MAX.assert(this.ctx.sequence < CrossChainSwap2.UINT_MAX,'input sequence should less than UINT_MAX')// Check if using block height.if (this.timeout < CrossChainSwap2.LOCKTIME_BLOCK_HEIGHT_MARKER) {// Enforce nLocktime field to also use block height.assert(this.ctx.locktime <CrossChainSwap2.LOCKTIME_BLOCK_HEIGHT_MARKER,'locktime should be less than 500000000')}assert(this.ctx.locktime >= this.timeout,'locktime has not yet expired')// Verify Bobs signature.assert(hash160(bobPubKey) == this.bobAddr, 'Bob wrong pub key.')assert(this.checkSig(bobSig, bobPubKey))}
}

源码文件crosschainswap2.ts

智能合约有两个公共方法:

  1. swap():如果 Alice 提供了她向 Bob 支付了足够数量的 BTC 的证据,则 Alice 会调用该函数来获取资金。
  2. cancel():由 Bob 在指定的时间过后调用以提取资金。

完整的代码和测试可以在 GitHub 上找到。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

windows10系统更新失败无法进入系统

用户反馈早上电脑重启&#xff0c;系统在更新卡好久好进去是否更新windows11&#xff0c;选否&#xff0c;重新就反复在更新中无法进入系统。我在测试的过程也是多次更新卡好久无法进入系统&#xff0c;而且出现下面提示 windows10系统更新失败无法进入系统&#xff0c;蓝屏提…

设备管理的方法与思路

阅读本文你将了解设备管理的思路与方法&#xff1a;一、制定全面的管理计划&#xff1b;二、标准化管理流程&#xff1b;三、设备维护与保养&#xff1b;四、风险管理与预防&#xff1b;五、引入数字化工具。 设备管理在生产制造领域是保障生产安全和效率的核心环节。通过引入…

java分布式锁分布式锁

java分布式&锁&分布式锁 锁 锁的作用&#xff1a;有限资源的情况下&#xff0c;控制同一时间段&#xff0c;只有某些线程&#xff08;用户/服务器&#xff09;能访问到资源。 锁在java中的实现&#xff1a; synchronized关键字并发包的类 缺点&#xff1a;只对单个的…

【Flutter】graphic图表的快速上手

简介 graphic是一个数据可视化语法和Flutter图表库。 官方github示例 网上可用资源很少,只有作者的几篇文章,并且没有特别详细的文档,使用的话还是需要一定的时间去调研,在此简单记录。 示例 以折线图为例(因为我只用到了折线图,但其他的图大差不差) 创建一个两个文…

世微 舞台灯深度调光 大功率 dc-dc降压恒流驱动IC APS54083

产品描述 APS54083 是一款 PWM 工作模式,高效率、外围简单、外置功率 MOS 管&#xff0c;适用于 5-220V 输入高精度降压 LED 恒流驱动芯片。输出最大功率150W最大电流 6A。APS54083 可实现线性调光和 PWM 调光&#xff0c;线性调光脚有效电压范围 0.5-2.5V.PWM 调光频率范围 10…

C++ :静态成员

静态成员 静态成员就是在成员变量和成员函数前加上关键字 static &#xff0c;称为静态成员 静态成员分为&#xff1a; 静态成员变量 1.所有对象共享同一份数据 2.在编译阶段分配内存 3.类内声明&#xff0c;类外初始化 静态成员函数 1.所有对象共享同一个函数 2.静态成…

第29期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大型语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以…

C# 实现微信退款及对帐

目录 需求 基础准备 关键代码 操作界面 ​编辑 退款订单类及方法 退款功能实现 对帐 支付商家后台相关要点 实时交易帐单查询 精确交易帐单查询 小结 需求 在招聘报名系统里&#xff0c;考务费支付是其中一个环节&#xff0c;支付方式很多种&#xff0c;比如银联、…

操作系统CLOCK算法

操作系统时钟(CLOCK)置换算法_时钟置换算法-CSDN博客 前七步相同 第八步的时候 发现页面在内存中 标记位变成1 但是指针不需要移动。

什么软件可以去视频水印?分享3个超实用去水印工具

什么软件可以去视频水印&#xff1f;短视频已然成为了我们日常生活或工作的一部分&#xff0c;当我们遇到感兴趣的视频想保存发现无法保存&#xff0c;或者保存后留有水印&#xff0c;非常影响我们视频观看度和分享欲&#xff0c;为了解决这一问题&#xff0c;许多针对视频水印…

如何用CHAT写“科技探索者”视频号运营方案

问CHAT&#xff1a;生成一篇“科技探索者”视频号运营方案&#xff0c;要求内容&#xff1a; &#xff08;1&#xff09;视频号的定位、面向的人群、主要发布哪方面的内容 &#xff08;2&#xff09;视频号的内容设计&#xff08;用什么样的方式来体现、最好有内容创意&#xf…

学习笔记-瑞吉外卖项目实战(一)

软件开发整体介绍 软件开发流程 角色分工 软件环境 瑞吉外卖项目介绍 项目介绍 产品原型介绍 技术选型 功能架构 角色 开发环境搭建 数据 创建database reggie&#xff0c;在里面创建表&#xff1a; maven 创建springboot项目并导入相关依赖坐标&#xff1a; 我们可以在项目…

【已解决】AttributeError: module ‘matplotlib‘ has no attribute ‘imshow‘

首先 在学习OpenCV的第一个程序&#xff0c;碰到这个问题记录一下。首先我已经安装好了matplotlib 如下图&#xff1a; 所以可以排除的就是我已经具备了这个库&#xff0c;那就是我在调用的时候出现的问题。 其次 回到pycharm&#xff0c;检查一下代码并做出如下的修改。 …

通达信抛物线SAR指标原理详解、参数设置及选股公式

抛物线指标(SAR)是由技术分析大师威尔斯威尔德(Welles Wilder)发明的&#xff0c;在其1978 年出版的《技术交易系统新概念》一书中介绍了该指标。SAR指标通过跟踪股票价格的动态变化&#xff0c;在走势图上以一系列点的形式显示&#xff0c;提供了一种判断趋势反转的方法&#…

鸿蒙应用开发-初见:入门知识、应用模型

基础知识 Stage模型应用程序包结构 开发并打包完成后的App的程序包结构如图 开发者通过DevEco Studio把应用程序编译为一个或者多个.hap后缀的文件&#xff0c;即HAP一个应用中的.hap文件合在一起称为一个Bundle&#xff0c;bundleName是应用的唯一标识 需要特别说明的是&…

某医院小程序存在支付漏洞和越权

某医院小程序存在支付漏洞和越权查看他人身份证&#xff0c;手机号&#xff0c;住址等信息 一个医院线上的小程序 登陆后点击个人信息&#xff0c;抓包&#xff0c;放到repeter模块&#xff0c; 修改strUserID参数可以越权查看别人信息 放intruder模块可以跑数据&#xff0c;这…

Redis缓存设计典型问题

目录 缓存穿透 缓存失效&#xff08;击穿&#xff09; 缓存雪崩 热点缓存key重建优化 缓存与数据库双写不一致 缓存穿透 缓存穿透是指查询一个根本不存在的数据&#xff0c; 缓存层和存储层都不会命中&#xff0c; 通常出于容错的考虑&#xff0c; 如果从存储层查不到数据…

MybatisPlus改造逻辑删除有多方便

MybatisPlus的逻辑删除可以有效保留历史数据。之前没有用逻辑删除的项目&#xff0c;想改造成逻辑删除总共需要几步&#xff1f; 答案&#xff1a;4步搞定 一、修改pom.xml的MybatisPlus版本&#xff08;注意版本兼容性&#xff09; <properties>...<!--<mybatis-…

anyRTC 融合音视频能力底座:助力企业数字化转型

随着全球化的发展&#xff0c;产业竞争日益激烈。数字化转型和创新成为了企业提高竞争力、实现可持续发展的重要手段&#xff0c;面对产业结构调整、资源环境挑战、数字技术与创新带来的行业颠覆与机遇&#xff0c;企业需要进行数字化转型和创新以适应新环境和新时代的挑战。 …

P13 C++ 类 | 结构体内部的静态static

目录 01 前言 02 类内部创建静态变量的例子 03 在类的内部创建静态变量的作用 04 最后的话 01 前言 本期我们讨论 static 在一个类或一个结构体中的具体情况。 在几乎所有面向对象的语言中&#xff0c;静态在一个类中意味着特定的东西。这意味着在类的所有实例中&#xff…