SimpleChain交易确认与回滚处理 SimpleChain2.0版本的更新已经支持了跨链交易,在自由公证人机制的跨链协议中,公证人需要对链上的交易进行签名,那么公证人如何确认一笔交易成功上链呢?下面我将和大家分享一下。
一、交易确认
用户在发起一笔跨链交易后,会通过RPC接口将请求发送到区块链节点的交易池中,交易池在经过验证后,会通过其连接的P2P网络广播这笔交易,详细流程分如下六个步骤:
节点接收交易:SimpleChain的节点(包括共识节点与同步节点)启动后,sipe协议会启动RPC服务,接收来自客户端的交易请求; 节点同步交易:SimpleChain节点开启p2p服务并与其他sipe节点建立连接后,会从其他节点同步交易数据; 置入交易池:当节点接收RPC或同步P2P网络的交易后,将其置入本地交易池。交易池会验证交易的合法性,并通过交易价格、nonce值对交易队列进行排序与替换; 提供可执行交易:当共识模块miner可以打包区块时,交易池会取出当前可执行的交易,交易在执行完成后被打包进区块; 广播交易:交易将以交易和区块的形式被广播,当交易池接受到新交易后,会通过P2P网络同步给其他的sipe节点;当交易被打包入区块后,交易将以区块的形式广播给其他节点;
图1. 交易池验证交易并广播
交易经过P2P网络的广播与转发后,会被发送至矿工节点,矿工节点在出块时,会将验证后的交易从交易池中取出,并在本地执行此交易生成该交易的回执receipt,并更改state状态,具体流程分以下几个步骤:
提取交易:共识模块从交易池中取出可以执行的交易,交付给执行器执行; 准备执行:执行器在获取到交易后,计算出交易的执行条件(手续费gas、交易类型、执行环境等)将交易封装为消息Message后,交给虚拟机EVM执行(跨链交易类型为普通合约交易); 执行交易:跨链合约将被编译为虚拟机EVM可以执行的汇编码,跨链交易通过调用合约方法修改合约地址的状态State,并生成执行的日志event log;
图2. 交易执行
在上述流程中,虚拟机在执行跨链交易成功后,会生成事件日志Event Log,并存入交易回执receipt结构中。矿工节点在执行完交易后,会将执行过的交易打包进区块中,然后以区块的形式通过P2P网络广播给其他节点。
跨链过程中,有如下三种形式的交易以及对应的事件日志:
发单交易maker:由发起链用户A在发起链客户端提交的交易,调用了跨链合约的makerStart接口,调用成功后会在跨链合约上锁定用户A的资产并生成MakerTx日志; 接单交易taker:目标链用户B相应跨链交易而提交的交易,调用了跨链合约的taker接口,调用成功后会向发起链用户A在目标链上的对应地址A’转移资产,并生成TakerTx日志; 解锁交易finish:锚定节点在确认跨链交易成功后对发起链跨链合约上用户A的资产进行解锁,并转移给目标链用户B在发起链上的对应地址B’,并生成MakerFinish日志;
图3. 跨链合约调用成功时emit产生event log
跨链协议公证人节点(又称锚定节点Anchor Peer)不参与出块,仅作为同步节点同步矿工节点生产的区块。在接收到来自同步模块的区块后,锚定节点首先会验证此区块的合法性,在确认区块是当前链的下一区块后,锚定节点会从块中取出交易,在本地环境下执行,同样,交易经虚拟机执行后,生成包含事件日志event log的回执。 跨链订阅器Subscriber用于订阅区块交易执行后生成的日志event log,支持SimpleChain2.0版本的各种主子链场景。对于使用PBFT、Raft共识的子链来说,订阅器无需等待确认高度,而对于使用Pow、Poa、Dpos共识的链来说,订阅器会将log保存在未确认区块日志队列UncomfirmedBlockLog的队列中,在经过n个区块的确认后(n可以由锚定节点启动参数进行配置),才将其取出提交到跨链协议处理。
图4. 跨链交易等待确认
跨链订阅器将交易日志封装为跨链协议的消息后,会当前区块与确认区块的跨链消息合并形成联合确认块Union Block,联合确认块高度为当前最新区块的高度,包含了最新区块中的状态变更事件Status Modify Event,及经过n个区块确认后的已确认事件Confirmed Event。
图5. 联合确认块
对于可能出现的拜占庭攻击Byzantine Attacks,Simplechain2.0跨链协议采用了多重签名Multi Signature的方式防止公证人节点作恶。跨链订阅器subscriber提交已确认消息后,跨链协议执行流程如下: 跨链处理器Handler提取联合确认块中消息,分为New Cross Event、Reorg Cross Event 以及 Confirmed Event 跨链处理器将Confirmed Event中的发单消息提交给跨链交易池CrossPool,交易池将消息签名后生成本地签名消息Local Signature Message保存到pending队列,并广播签名消息给其他锚定节点 从其他锚定节点接收到的签名消息Remote Signature Message时,提交到跨链交易池的Queue队列,当跨链处理器接收到订阅器的对于跨链消息后,将Queue队列中的签名消息合并到pending队列 当签名数量达到拜占庭确认需要的签名数(2n+1,n为容许的恶意节点数量)时,将附带多重签名消息的跨链交易存入跨链存储器Cross Store,至此为止,跨链交易完成确认。
图6. 跨链协议执行确认过程
回滚处理 跨链协议在跨链的过程中,需要通过同步到的区块即时得处理跨链状态,然而对于SimpleChain的Pow、Poa共识来说,最近产生的区块易发生回滚,在链因区块回滚切换链分叉的同时,跨链协议也要随之做出响应。 SimpleChain2.0锚定节点在同步到包含跨链交易的新区块时,处理流程如下: 新区块的父区块为当前链头区块,将新区块插入到当前链中 新区块的父区块不为当前链头区块,判断当前链与新区块所在分叉链的总难度 新区块所在分叉链难度较高,调用Reorg函数将当前链切换至分叉链,回滚旧链区块生成日志deletedLogs,切换新链生成日志rebirthLogs,调用NotifyBlockReorg通知订阅器subscriber区块发生回滚 调用StoreCrossContractLog方法将新插入区块日志提交给跨链订阅器subscriber
图7. 跨链订阅器处理交易log
SimpleChain的回滚需要处理以下三种情况,根据复杂度排列如下: 单个区块回滚:在同一区块高度下,新区块直接替换旧区块;
图8.1 单个区块回滚日志处理
多个区块回滚:回滚当前链上的多个区块,切换到最新块所在的分叉链;
图8.2 多个区块回滚日志处理
分叉链来回切换:两条链分叉竞争激烈,频繁发生回滚链切换。 以上这些情况,虽然看起来一个比一个复杂,但其实处理的总体思路是一样的,当区块发生回滚时,首先由区块高度从高到低收集旧链回滚的区块log,记为deletedlogs,然后搜集由区块高度从低到高排列的新链的区块log,记为rebirthlogs,对于每个deletedlogs修改的跨链状态,统一回滚至上一个状态;对于每个rebirthlogs,顺序更新跨链状态。 同时,在订阅器的uncomfirmedBlockLog中,也要对未确认的deletedlogs和rebirthlogs进行处理,删除不在当前区块链上的deletelogs,并添加新链的rebirthlogs等待确认。
图9. 区块回滚日志处理
总结 对于独立的区块链来说,链本身的共识算法可以保证交易执行与状态更改的一致性,即使当共识结果(区块)发生回滚时,交易的执行结果与执行后导致的状态更改也会相应地进行回滚,然而对于横跨两条甚至多条链的跨链交易来说,服从的共识机制不一致,交易状态的确定是至关重要的。目前SimpleChain主链参考了多区块确认交易的思想,通过一定数量区块的确认,保证了跨链交易状态的安全。 未来,SimpleChain跨链也将引入支持BFT验证的子链,在保证交易状态不可撤销的同时,大大提升跨链交易执行的速率。