NOTE协议使基于比特币UTXO模型的区块链能够创建及管理数字资产。该协议支持强加密数据存储与通信,亦适用于公开透明的数据存储,包括Token与NFT等数字资产的所有权管理。
本协议基于BIP32标准,确定去中心化身份(DID)的生成规则。
针对加密数据,本协议采用DID规则,对每条记录以难以预测的随机公私钥加密解密,并使用Electrum BIE1 ECIES算法进行数据加密。
协议明确数据存储格式,并定义了数据的增删改查及分享规则。
信息安全无须依赖第三方信任,仅助记词持有者可访问数据,确保数据安全与存储安全。
利用链上智能合约进行比特币共识级别的资产校验,结合链下资产索引器,高效解读链上资产并提供资产的默克尔证明。
此为一种第二层解决方案,基于牢不可破的比特币协议及其底层区块链共识规则。本协议也为Layer 2网络奠定应用基础需求。
基于UTXO模型的区块链特点,本协议解决以下问题:
- 去中心化身份(DID)
- 数据格式
- 数据存储位置
- 数据所有权确认
- 所有权转移
- 链上合约
- 数据解析
- 数据索引
- 资产创建
- 资产挖掘
- 资产转移
- 资产销毁
- 资产通知
- 资产证明
设计过程中考虑了交易顺序,以避免双重支付、减少链上数据冗余,以及防止资产误消耗等问题。
在用户的终端设备(如手机或电脑)上,基于BIP32协议派生账户公私钥和用于数据加密的私钥。这些私钥作为去中心化身份标识,使用公开的账户公钥来标识用户。在所有权确认、签名、数据创建和分享等所有场景中均使用此身份。
账号密钥基于以下路径派生:
m/purpose'/coin_type'/account'/target/index
在NOTE.SV软件中使用了下面的变量
purpose = 44
coin_type=236
account=0
target=0
index=0
完整的派生路径为:
m/44'/236'/0'/0/0
顺序增加index可以创建多账号。
数据加密密钥的派生路径定义如下:
m/purpose'/coin_type'/account'/target/quotient/remainder
在NOTE.SV软件中,使用了以下变量:
purpose = 44
coin_type = 236
account = 0
target = 2
派生路径的生成步骤如下:
- 随机生成一个64位整数 n。
- 遵循IEEE754标准,对随机数取模
n % (2^53-2) + 1
,生成派生索引。 - 使用派生索引除以Hardened,获取商和余数。代码如下:
const Hardened = 0x80000000; const quotient = Math.floor(index / Hardened); const remainder = index % Hardened;
完整的派生路径为:
m/44'/236'/0'/2/${quotient}/${remainder}
链上数据的格式和顺序规定如下:
- 公钥HASH:持有者的账号公钥的HASH160。
- 明文HASH:
- 如果是加密信息,则为明文的SHA256值。
- 如果是公开数据,则为0x00。
- 数据:明文或密文。数据可为加密或公开数据。原始数据使用Msgpack协议编码,需排序键值(sortKeys=true)。
- 签名:使用持有者账号私钥对明文HASH进行的签名。签名可通过持有者账号公钥验证。签名算法采用Bitcoin Message标准。如果可以提供交易的公钥签名,此处为0x00;否则必须有签名。
- 附加信息:描述数据的表现形式
- 1字节的整数0x00,表示数据使用了持有者的账号公钥加密。
- 1字节的整数0xff,表示数据未加密。
- 8字节的整数,范围:1~2^53 - 1,表示数据使用了数据加密公钥加密。
- NOTE:全大写,固定的协议标识符。
数据需放置在交易的解锁脚本中。在解锁过程中,矿工将对交易签名和其他解锁条件进行校验。同时,输出部分也需要有相应的脚本输出,以形成交易链条。索引器会根据区块和UTXO交易链确定交易的执行顺序,并据此验证资产交易的有效性。此类解锁签名的flag设置为 SINGLE | ANYONECANPAY。 本协议采用非标准脚本,与P2PKH等标准脚本不同,从而避免UTXO被误消费的情况。 本协议所使用的最简单比特币脚本示例如下。
非标脚本按照以下格式定义:
解锁脚本:交易签名 公钥HASH 明文数据Hash 数据 数据签名 附加信息
锁定脚本:NOTE OP_2DROP OP_2DROP OP_2DROP 原公钥 OP_CHECKSIG
交易输出:NOTE OP_2DROP OP_2DROP OP_2DROP 新公钥 OP_CHECKSIG
在支持P2WSH的区块链中,格式定义如下:
解锁脚本:交易签名 公钥HASH 明文数据Hash 数据 数据签名 附加信息
锁定脚本:NOTE OP_2DROP OP_2DROP OP_2DROP 原公钥 OP_CHECKSIG
输出脚本:NOTE OP_2DROP OP_2DROP OP_2DROP 新公钥 OP_CHECKSIG
脚本地址:赎回脚本的HASH地址
数据信息被保存在隔离见证数据区中。
类似于P2WSH,赎回脚本作为MAST的一个解锁分支。由包含数据解锁脚本提供解锁。 在支持P2TR的区块链中,格式定义如下:
解锁脚本:交易签名 公钥HASH 明文数据Hash 数据 数据签名 附加信息
锁定分支脚本:NOTE OP_2DROP OP_2DROP OP_2DROP 公钥 OP_CHECKSIG
输出分支脚本:NOTE OP_2DROP OP_2DROP OP_2DROP 公钥 OP_CHECKSIG
交易输出:Taproot地址输出
解锁脚本信息保存在隔离见证数据区中。
建议使用非标脚本和P2WSH以获取更清晰的语义。P2TR MAST可实现更复杂的交易逻辑,但可能导致索引器设计更为复杂。
通过更复杂的锁定脚本,可以创建链上智能合约,使得只有符合合约条件的交易才能被确认上链。以下是一个简单示例:该脚本要求,除了签名外,还必须提供特定的消息(message),才能发起交易并使信息成功上链。
class Scryptdemo extends SmartContract {
@prop()
static note: ByteString = toByteString('NOTE', true)
@prop()
pubKey: PubKey
@prop()
hash: ByteString
constructor(hash: Sha256) {
super(...arguments)
this.hash = hash
}
@method()
public unlock(
sig: Sig,
message: ByteString,
owner: ByteString,
plainHash: ByteString,
data: ByteString,
hashSig: ByteString,
extra: bigint
) {
Scryptdemo.note
// owner
// plainHash
// data
// hashSig
// extra
assert(sha256(message) == this.hash, 'Hash does not match')
assert(this.checkSig(sig, this.pubKey), 'signature check failed')
}
}
编译后的脚本为
044e4f54450000<hash>6175615279755879a85179876959795279ac77777777777777777777
ASM:
4e4f5445 <hash> 0 0 OP_NOP OP_DROP OP_NOP OP_2 OP_PICK OP_DROP OP_8 OP_PICK OP_SHA256 OP_1 OP_PICK OP_EQUAL OP_VERIFY OP_9 OP_PICK OP_2 OP_PICK OP_CHECKSIG OP_NIP OP_NIP OP_NIP OP_NIP OP_NIP OP_NIP OP_NIP OP_NIP OP_NIP OP_NIP
示例合约使用Scrypt制作。
无论是最简单的合约还是更复杂的合约,在由解锁脚本和锁定脚本构成的交易脚本中,数据的格式和顺序都必须遵循本协议的规定。由于支持智能合约,链上Oracle和Swap等功能也将成为可能。
数据上链必须通过花费符合本协议规定的UTXO来完成交易签名或数据签名。链上矿工以及链下索引和钱包通过检查签名来确认数据所有权。UTXO链保证交易顺序,防止双重支付。数据签名和交易签名的二选一机制允许第三方代付交易费用。如果未提供数据签名,则交易签名者被视为数据的持有者。 数据所有权可通过以下步骤确认:
- 如果存在数据签名,首先检查持有者的数据签名,提取公钥,并与持有者的公钥HASH一起验证。如果验证通过,则所有权归公钥持有者。如果验证不通过,则该交易为非法交易。
- 如果未提供数据签名,则提供交易解锁的公钥即为数据所有者。
- 获取接收方的公钥。
- 计算接收方公钥的HASH。
- 使用发送方的账户私钥进行签名。
- 代付方或发送方使用私钥签名交易。
- 获取接收方的公钥。
- 将交易输出到对方的公钥脚本或公钥脚本的HASH。
- 将接收方的HASH数据设置为0x00,以节约交易空间。
- 发送方使用私钥签署交易。
交易发布到区块链后,数据索引器对交易进行解析,检查签名以确认所有权是否符合协议,并解析数据内容以确定其有效性。不符合规定的交易将被丢弃。大量的非合规交易可通过垃圾邮件过滤器标记发起方。
加密数据的创建过程如下:
- 准备明文数据内容。
- 使用msgpack对数据进行打包。
- 获取打包数据的SHA256 HASH。
- 生成随机数,创建派生索引,并根据索引派生出加密私钥。
- 使用派生出的公钥对数据进行加密。
- 使用账户私钥对加密后的数据进行Bitcoin Message签名。
- 构建数据脚本。
- 构造交易并广播。
加密数据转让时的步骤:
- 转让加密数据时,设置附加数据为0。
- 获取交易对方的公钥。
- 使用对方公钥加密数据。
- 使用自己的根私钥进行签名。由于从签名中可以提取出公钥,因此可以确认自身身份。
- 设置交易对方的公钥HASH。
- 接收方在解密数据后可以验证明文的Hash256。
接收方公钥HASH 明文Hash 加密数据 持有者的数据签名 00 NOTE
由于比特币区块链的愿景和技术限制,本协议不要求也不建议将大量数据存储在区块链上。只需将数据的HASH上链,数据本身可以存储在其他去中心化或中心化系统中。
TODO
TODO
TODO
感谢以下列出及未列出的所有个人和团队对比特币的贡献,他们的文章和代码给予了我们极大的启发。
白皮书 - 牢不可破的比特币协议。
BIP32 定义了一套通过助记词派生私钥的算法,可用于获取相应的公钥和公钥哈希(即地址)。
Electrum BIE1 ECIES 定义了使用椭圆曲线算法进行数据加密和解密的方法。
Paymail 启发了我们的DID设计。
Ordinals 促使我们升级协议。
BRC-20 对标准数据格式提出了建议。
Atomicals 帮助我们更好地理解需求。
Scrypt 带来比特币智能合约
Msgpack 节省每一个字节