Liquid的Covenants:处理比特币脚本中的金额

1. 引言

Covenants契约是一种允许introspection自省的结构:

  • 交易output可以对花费其的交易施加条件(超出特定的“必须提供自身的有效签名和特定的公钥”)。

Rusty Russell 之前研究过Covenants: Examining ScriptPubkeys in Bitcoin Script,但契约想要强化的另一个有用的事情是金额。很容易实现相等,但需考虑允许合并输入的情况:

  • 也许第一个output必须是第一个和第二个输入的总和。

问题是比特币脚本处理的是带符号的补码值,而 31 位限制了最多 21.47483648 个比特币。但是,使用OP_MULTISHA256OP_CAT,可以处理全额。

2. 令人烦恼的金额问题

使用OP_TXHASH,可在stack上获得 SHA256(输入金额)SHA256(输出金额)。由于这涉及哈希,因此除了相等之外,无法评估数字,因此在没有完全完整契约Covenants in Bitcoin: A Useful Review Taxonomy的其他情况下:

  • 需要让用户提供实际值到witness stack上,
  • 然后测试这些值来确定想要的条件,
  • 然后确保它们与OP_TXHASH交易中的内容相符。

Rusty Russell通常反对这种向后的形式(只需给stack上的值!),但无论如何都无法原生使用源自 OP_TX 的64 位值(建议push两个值,尽管其有点ugly)。

3. 比特币脚本可以处理的价值形式

2100万个 BTC 略低于 2^51 聪。

将这些位分成一组堆栈值:

  • lower:低24位
  • upper:高位(27,但可最多允许到 31)

将此元组称为“脚本友好对”(Script-friendly pair, SFP) 形式。请注意,stack上的所有脚本数字均以little-endian表示,并带有符号位(最后一个字节为 0x80)。不幸的是,这是一种令人讨厌的格式。

4. 将SFP转换为 8 字节 Little-Endian 值

下面的代码采用positive CScriptNum,并生成2个stack值,可以将这2个stack连接起来形成一个 4 字节无符号值:

# !UNTESTED CODE!
# Stack (top to bottom): lower, upper
OP_SWAP# Generate required prefix to append to stack value to make it 4 bytes long.
OP_SIZE
OP_DUP
OP_NOTIF# 0 -> 00000000OP_DROP4 OP_PUSHDATA1 0x00 0x00 0x00 0x00
OP_ELSEOP_DUP1 OP_EQUAL OP_IF# Single byte: prepend 0x00 0x00 0x00OP_DROP3 OP_PUSHDATA1 0x00 0x00 0x00OP_ELSEOP_DUP2 OP_EQUAL OP_IF# Two bytes: prepend 0x00 0x002 OP_PUSHDATA1 0x00 0x00OP_ELSE3 OP_EQUAL OP_IF# Three bytes: prepend 0x001 OP_PUSHDATA1 0x00OP_ELSE# Prepend nothing.0OP_ENDIFOP_ENDIFOP_ENDIF
OP_ENDIF
OP_SWAP# Stack (top to bottom): upper, pad, lower

这46个字节处理upper。现在lower是 0 到 16777215 之间的 CScriptNum,想要生成两个stack值,可将它们连接起来形成一个 3 字节无符号值。此时必须删除四字节情况下的零填充:

# !UNTESTED CODE!
# Stack (top to bottom): upper, pad, lower
OP_ROT# Generate required prefix to append to stack value to make it 3 bytes long.
OP_SIZE
OP_DUP
OP_NOTIF# 0 -> 000000OP_DROP3 OP_PUSHDATA1 0x00 0x00 0x00
OP_ELSEOP_DUP1 OP_EQUAL OP_IF# Single byte: prepend 0x00 0x00OP_DROP2 OP_PUSHDATA1 0x00 0x00OP_ELSEOP_DUP2 OP_EQUAL OP_IF# Two bytes.  Now maybe final byte is 0x00 simply so it doesn't# appear negative, but we don't care.1 OP_PUSHDATA1 0x00OP_ELSE# Three bytes: empty append below3 OP_EQUAL OP_NOTIF# Four bytes, e.g. 0xff 0xff 0xff 0x00 # Convert to three byte version: negate and add 2^23# => 0xff 0xff 0xff OP_NEG4 OP_PUSHDATA1 0x00 0x00 0x80 0x00 OP_ADDOP_ENDIF# Prepend nothing.0OP_ENDIFOP_ENDIF
OP_ENDIFOP_SWAP
# Stack (top to bottom): lower, pad, upper, pad

可稍微优化这 47 个字节。

现在使用OP_MULTISHA256(或OP_CAT 3 次 和OP_SHA256) 将它们连接起来形成一个 8 字节的little-endian数,以便与OP_TXHASH所使用的格式进行比较。

基本上,95 个字节用于将元组与哈希值进行比较。

5. 添加两个SFP

编写一些代码来添加两个格式良好的SFP!

# !UNTESTED CODE!
# Stack (top to bottom): a_lower, a_upper, b_lower, b_upper
OP_ROTOP_ADD
OP_DUP
4 OP_PUSHDATA1 0x00 0x00 0x00 0x01
OP_GREATERTHANOREQUAL
OP_IF# lower overflow, bump upper.# FIXME: We can OP_TUCK this constant above!4 OP_PUSHDATA1 0x00 0x00 0x00 0x01OP_SUBOP_SWAPOP_1ADD
OP_ELSEOP_SWAP
OP_ENDIF# Stack now: a_upper(w/carry), lower_sum, b_upper.
OP_ROT
OP_ADD
OP_SWAP
# Stack now: lower_sum, upper_sum

请注意,这 26 个字节不会检查upper是否溢出:若处理已验证的金额,甚至可以在可能之前添加 16 次(当然,对于不同的金额,这是不可能的)。不过,可在最后的OP_SWAP前,添加OP_DUP 0 OP_GREATERTHANOREQUAL OP_VERIFY

6. 检查SFP

上面的代码假设格式良好的pairs,但由于这些pairs源自witness stack,因此需要有一个routine来检查某pair是否格式良好:

# !UNTESTED CODE!
# Stack: lower, upper
OP_DUP
# lower must be 0 - 0xFFFFFF inclusive
0
4 OP_PUSHDATA1 0xFF 0xFF 0xFF 0x00
OP_WITHIN
OP_VERIFYOP_OVER
# upper must be 0 - 0x7FFFFFF inclusive
0
4 OP_PUSHDATA1 0xFF 0xFF 0xFF 0x07
OP_WITHIN
OP_VERIFY

这确保了范围都在规格范围内:没有负数,没有巨大的数字。

7. 总结

虽然这表明OP_CAT/OP_MULTISHA256足以处理脚本中的比特币金额,但其大小(约 250 字节以验证两个输入等于一个输出)为优化提供了相当引人注目的案例。

值得注意的是,这就是 Liquid 选择在比特币脚本中添加以下 64 位操作码的原因:

  • OP_ADD64 ,
  • OP_SUB64,
  • OP_MUL64,
  • OP_DIV64,
  • OP_NEG64,
  • OP_LESSTHAN64,
  • OP_LESSTHANOREQUAL64,
  • OP_GREATERTHAN64,
  • OP_GREATERTHANOREQUAL64。

【Liquid团队还重新启用了bitwise操作码(OP_XOR等)以使其能够很好地工作。还实现了OP_SCRIPTNUMTOLE64、OP_LE64TOSCRIPTNUM和OP_LE32TOLE64进行转换。】

在Rusty Russell之前的文章中,建议OP_LESS适用于任意值,但不适用于这些值,因为endian字节序是错误的!至少,需要添加OP_LESSTHAN64、OP_ADD64和OP_NEG64来允许 64 位比较、加法和减法。

但是,仅使用OP_CAT或OP_MULTISHA256,就可以处理金额。只是不够优美!

参考资料

[1] Blockstream团队 Rusty Russell 2023年10月22日博客 Covenants: Dealing with Amounts in Bitcoin Script

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

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

相关文章

两相欠压继电器 WY-35A3 额定输入电压100V 导轨安装 JOSEF约瑟

系列型号: WY-35A4电压继电器;WY-35B4电压继电器; WY-35C4电压继电器;WY-35D4电压继电器; WY-35A4D电压继电器;WY-35A4T电压继电器; WY-35B4D电压继电器;WY-35B4T电压继电器&#xf…

人工智能时代过失犯理论的挑战与应对—以自动驾驶汽车交通肇事为例

内容提要以自动驾驶汽车为代表的人工智能产品致害所涉犯罪主体复杂多样、前置性规范缺失, 以及人工智能产品固有的自主与黑箱特性等问题给过失犯理论带来了变革的压力与挑战。传统过失犯理论、新过失犯理论以及客观归责理论都无法解决人工智能产品致害所涉过失犯罪认定问题。人…

【VMware】虚拟机及镜像Ubuntu安装

Vmware 一.VM是什么?有什么用?二.下载VMware Wworkstation Pro三.安装虚拟机四.安装镜像 一.VM是什么?有什么用? vmware是一款运行在windows系统上的虚拟机软件,可以虚拟出一台计算机硬件,方便安装各类操作…

K8s学习七(服务发现_2)

Ingress Service 主要用于集群内部的通信和负载均衡,而 Ingress 则是用于将服务暴露到集群外部,并提供灵活的 HTTP 路由规则。在实际应用中,它们通常结合使用,Service 提供内部通信和负载均衡,Ingress 提供外部访问和…

网络工程师笔记18(关于网络的一些基本知识)

网络的分类 介绍计算机网络的基本概念,这一章最主要的内容是计算机网络的体系结构-ISO 开放系统互连参考模型,其中的基本概念,例如协议实体、协议数据单元,服务数据单元、面向连接的服务和无连接的服务、服务原语、服务访问点、相…

蓝桥杯练习题 —— 高精度加法(python)

python优势 # encoding utf-8 # 开发者:xxx # 开发时间: 16:48 # "Stay hungry,stay foolish."a int(input()) b int(input())print(a b) 正常 # encoding utf-8 # 开发者:xxx # 开发时间: 16:48 #…

大数据分层存储架构:ODS、DWD、DWM与DWS详解

在大数据领域中,ODS、DWD、DWM和DWS代表了数据仓库的不同层次,它们共同构成了大数据的分层存储结构。这种结构的设计有助于提高数据查询效率,降低成本,并满足不同的业务需求。 ODS(Operational Data Store&#xff09…

计算机视觉领域主流优秀的模型的用处与区别,优劣。复合缩放方法,深度可分离卷积

目录 计算机视觉领域主流优秀的模型的区别,优劣 YOLO (You Only Look Once) ResNet、EfficientNet 优劣与应用场景

1.k8s简介

目录 k8s是什么 k8s不是什么 云原生 微服务 整体式架构与微服务架构 微服务的特性 微服务的优势 k8s是什么 Kubernetes 是一个可移植、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。 Kubernetes 拥有一个庞大且快…

除了sql外还有那些查询语言

除了SQL(结构化查询语言)外,还有许多其他的查询语言,包括但不限于XQuery(对XML的查询语言)、MDX(多维查询语言,用于分析数据仓库)、DQL(数据查询语言&#xf…

聊一聊,JMeter分布式性能测试!

在做后端服务器性能测试中,我们会经常听到’分布式’。但你是否了解分布式呢?今天,我们就来给大家讲讲,在企业实战中,如何使用分布式进行性能测试,实战过程中,又有哪些地方要特别注意&#xff1…

pyqtgraph 实时更新柱状图

import sys import numpy as np from PyQt5.QtWidgets import QApplication, QMainWindow import pyqtgraph as pgclass MainWindow(QMainWindow):def __init__(self):super().__init__()self.plot_widget pg.PlotWidget(title实时更新的柱状图)self.setCentralWidget(self.pl…

C++ //练习 11.22 给定一个map<string, vector<int>>,对此容器的插入一个元素的insert版本,写出其参数类型和返回类型。

C Primer&#xff08;第5版&#xff09; 练习 11.22 练习 11.22 给定一个map<string, vector<int>>&#xff0c;对此容器的插入一个元素的insert版本&#xff0c;写出其参数类型和返回类型。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具…

法向量估计

法向量估计 1. 求解点P法向量的原理2. 法向量估计的证明3. 为什么求点P的法向量&#xff0c;需要使用以P为中心的邻域内的点&#xff1f;4. 法向量估计的应用和思考5. 权重法向量估计 1. 求解点P法向量的原理 已知有一组点 P ( p 1 , p 2 , p 3 , . . . , p n ) , p i ∈ R 3…

算力在现实生活中的多方面应用!

算力在现实生活中的应用是多方面的&#xff0c;它已经成为推动现代社会发展的重要力量。 以下是算力在不同领域中的具体应用&#xff1a; 立即免费体验&#xff1a;https://gpumall.com/login?typeregister&sourcecsdn #分布式云服务#算力#GpuMall#GpuMall智算云#训练#…

零代码与低代码开发平台

1、什么是低代码开发平台&#xff1f;什么是零代码开发平台&#xff1f; 零代码开发平台&#xff1a; 指的是不需要写代码就能够快速开发出业务应用/系统的平台。我们在工作中使用的业务应用&#xff0c;主要提供数据收集、数据处理、数据流转和展示等功能。零代码开发平台能够…

理解vue2中的computed计算属性与缓存机制

vue实例组件初始化过程中&#xff0c;在执行initState(vm)方法初始化状态时&#xff0c;判断options.computed有值时会进行initComputed$1(vm,options.computed)处理 function initState(vm) {let options vm.$options;// 省略props methods data的处理// 处理计算属性comput…

蓝桥杯 【日期统计】【01串的熵】

日期统计 第一遍写的时候会错了题目的意思&#xff0c;我以为是一定要八个整数连在一起构成正确日期&#xff0c;后面发现逻辑明明没有问题但是答案怎么都是错的才发现理解错了题目的意思&#xff0c;题目的意思是按下标顺序组成&#xff0c;意思就是可以不连续&#xff0c;我…

JavaScript的函数基础

目录 前言: 1.函数是什么: 2.函数的基本使用: 2.1 定义函数: 2.2. 调用函数 2.3函数命名规范: 2.3.1由数字、字母、下划线组成&#xff1a; 2.3.2区分大小写&#xff1a; 2.3.3不能数字开头&#xff0c;也不能是关键字&#xff1a; 2.3.4自定义函数纯小写&#xff1a…

set feedback 和set define

set feedback set feedback有三种方式 set feedback on set feedback off set feedback n set feedback on: 打开反馈 默认情况下&#xff0c;当一条 sql 语句执行的时候&#xff0c;oracle 会给一个反馈&#xff0c;比如&#xff1a;创建表的时候&#xff0c;如果成功&#x…