下午好,亲爱的读者们!
本文是关于等离子现金链的,并阐明了以下主题:
- 可伸缩性难题及其解决方法;
- 子链数据结构及其在根链中的显示;
- 实施对根链的投入;
- 执行从根链中撤出。
Opporty使用Javascript编程语言来实现子链以及根链的Solidity。 这些语言提供了代码示例。

区块链和去中心化使得优化和改善几乎所有使用互联网和信息技术的生活领域的工作成为可能。 它们提高了可靠性,财务效率,还促进了实物和商品的数字化。
智能合约将业务逻辑带入分散式网络。 这使您可以构建新的DAPP应用程序。
智能合约的执行和具有分布式数据库的应用程序的快速操作只有在满足可伸缩性条件的情况下才能实现。
现代分散式区块链有几个缺点。 主要的是可伸缩性。 以太坊进程约为20 tx / s。 在现代金融现实中,这还不够。 同时,以太坊具有防止黑客入侵和网络故障的最高防护等级。 构建在区块链上的其他加密货币和系统没有如此高度的分散性,从而降低了对网络的信任。
可伸缩性难题
区块链可伸缩性难题包括三个部分:
困境中的权力下放
顾名思义,去中心化反映了区块链中活动所有权的多元化程度,以及创建区块和生成新分类账条目的多元化程度。
为了清楚起见,有必要讨论最集中的组织。 通常,使用简单的数据库而不是区块链。 这样的组织是由特殊管理员经营的。 可以通过手动干预取消所有交易。
在完全分散的网络中,每个用户都可以参与构建网络。
去中心化的最重要结果是,大部分价值流向了参与创建区块链的社区。 没有能够获得所有收益的中级管理人员团队,而不是那些自己产生网络结构的中级管理人员团队。 实际上,大多数加密项目完全由其贡献者或用户而非创始人所有。 对于那些不是创始人的人来说,这显然是一种更具吸引力的模式。
困境中的安全
这与区块链抵御来自外部来源的攻击并使系统保持不变状态的能力有关。 大多数区块链都受到许多潜在的安全威胁。 必须了解最常见的攻击媒介和防御选项。
在这种情况下,权力下放和安全是密不可分的。 节点越多,网络对集中侧的依赖就越少,因此,具有中心故障点的风险也就越小。 但是,还有许多其他攻击媒介对分散网络构成威胁,包括:
>
50%的攻击 -拥有超过未支付令牌总数50%的对象实际上拥有网络;
>
Sybil攻击 -用户可以在系统中生成许多标识符,以有效控制网络所有权和/或决策中的重要份额;
>
DDoS-意图破坏网络流量,使恶意交易充满网络时,就会发生分布式拒绝服务(DDoS)攻击;
>
串通攻击 -一个或几个对象(或节点)决定联合起来对网络执行任何恶意操作。
困境中的可伸缩性
可扩展性的程度很重要,因为它决定了最终吞吐量,即网络大小的上限。 评估网络时最要问的问题是:“该系统可以承受多少用户?” 比特币目前拥有2.9至580万个钱包持有者。 EOS有数千名成员。
可伸缩性和分散性可以共存,但安全性降低。 开发人员选择最适合他们需求的平台。 用户也一样。 双方的意见有时会有所不同。 一些用户愿意为可伸缩性牺牲安全性,另一些用户愿意为安全性牺牲可伸缩性,但是平衡要困难得多。
区块链技术中的“圣杯”
根据定义,区块链仅具有以下三个属性中的两个:
- 权力下放 (每个参与者只能访问O©资源,即普通笔记本电脑或小型VPS);
- 可伸缩性 (处理事务的能力O(n)> O©);
- 安全性 (使用O(n)资源防御入侵者)。

绿色:三个条件的平衡状态。
红色:安全性强,但分散和可扩展性有限。
蓝色:效率高,但是安全性和分散性受到限制。
黑色:分散性很高,但是没有可扩展性和安全性方面。
灰色:完全分散,安全性和可伸缩性的质量极低或缺失。
紫罗兰色:安全性和可伸缩性之间的平衡,拒绝分散。
区块链技术中的“圣杯”意味着将所有三个方面结合起来。
在当前大多数使用加密货币的项目中,实现了两个基本属性:去中心化和安全性。 可伸缩性受到影响。
解决难题的有前途的解决方案
权益证明(PoS)
股权证明(PoS)提供了潜在的可扩展性增强功能。 POS取代了基于工作量证明(PoW)系统的加密货币挖掘。 验证器的选择非常快速-以确定性方式进行。 同时,没有能源成本,而且是环保的。
侧链
在以太坊虚拟网络中,有可能创建一个边网,在该边网中项目可以处理其单个交易,然后仅将初始和最终结果记录在以太坊网络中。 这样可以减少EVM上的负载,但可以增强对侧链管理的信心。 因此,对第三方的信任减少了权力下放。
分片
分片可将事务分解为较小的数据。 代替将网络中的每个单独的节点处理整个事务,将节点分为几组,这些节点组处理某些数据。 后来,在处理期间,这些数据被重新同化以永久存储在区块链上。
增加块大小
Litecoin和比特币现金(BCH)是比特币区块链的“叉子”。 分叉基本上复制了一个区块链。 分支后,您可以进行更改。 LTC和BCH都增加了每个块的大小,从而允许每个块存储更多的交易,从而提高了交易的处理速度。
闪电网络
最早的侧链解决方案是闪电。 闪电网络的主要思想是,并非所有交易都应记录在区块链中,因为这会使网络超载。 如果用户多次相互转账,则注册每次转账是可选的。 只需打开一种支付渠道并在区块链上写下有关其开放数据就足够了。 该通道将根据需要保持打开状态。 当需要关闭它时,在此通道中进行的所有交易的结果都将被简单地写入区块链。 遵循这个想法,您可以创建一个完整的支付渠道网络。 然后,区块链上的交易将不那么频繁地使用。
付款渠道只是几笔交易的组合。 通道可以由其任何成员关闭。 这项操作就像打开保险箱一样,它使您可以提取参与者的资金,并记录他们向区块链转移时的数据。
当几个这样的通道组合到一个称为“闪电网络”的网络中时,这项技术将变得真正强大。 该网络是专门为比特币构建的。
雷电网络
对于以太坊来说,闪电最著名的对手是雷电网络。
这是在主区块链之外扩展的解决方案。 它与双向支付渠道中的ERC-20令牌传输兼容。
它的基本体系结构很复杂,但是与Raiden的交互要求开发人员仅与API交互才能在Raiden上创建可扩展的应用程序。
Raiden旨在提供即时付款和低佣金,提高交易保密性和小额付款。 大多数支付渠道都存在于网络外部,并且仅偶尔在根链内形成交易,这大大降低了子链的吞吐量。
最佳解决方案
闪电思想家创建了一个新的子链概念,以解决区块链速度问题。
机会实际上实施了等离子和等离子现金的概念。
Plasma是一组在以太坊根链之上运行的智能合约,由以分层树结构连接到根链的子链网络组成。
也就是说,以太坊根链的安全性用于优化可伸缩性。
等离子现金:机会选择
Opporty在第一个版本中使用Plasma Cash的实现。就可伸缩性而言,此模型是最有效的等离子体实现。
Plasma Cash是基于对Plasma链中每个令牌使用唯一标识符的系统。 也就是说,应用了NFT,并且网络中的令牌接收到唯一的序列号。
等离子现金的特点:
- 在客户端进行分片验证-客户只需要监视其Plasma链即可获取令牌。 这意味着事务吞吐量可以增加而不会增加单个用户的负担。
- 简化大规模出口-大规模出口对网络的威胁较小,因为小偷必须为他要窃取的每个令牌提交出口交易。
- 没有双向确认-交易不再需要两步发送和确认。 相反,只要将交易包含在主链中,就可以将其花费。
缺点:
大面额的令牌-由于必须为每个令牌分配一个序列号,因此不可能生成任意小的令牌。 这是由于以下事实:在某些时候,代币购买的价值将大于代币本身的价值。
等离子现金交易结构
Opporty使用Javascript来实现子链。 Opporty Plasma Cash中的每笔交易都是类似的结构:
const transactionFields = [ {name: 'prevHash'}, {name: 'prevBlock', int: true, default: 0}, {name: 'tokenId', isDecimal: true}, {name: 'newOwner'}, {name: 'type'}, {name: 'signature'}, ]
这里的主要元素是指向上一个prevBlock块的链接(需要在块链中移动),tokenId令牌标识符(它必须是唯一的)以及newOwner令牌的最后所有者。
此外,为了组装块并获得根链哈希,使用了特殊类型的Patricia Merkle Trie树。 以太坊使用同一棵树。 它具有压缩外观。 同时,您仍然可以接收包含或不包含交易的证明。
签名是椭圆曲线上的签名。
仅当令牌具有给定tokenId的情况下,使用令牌的交易才有效,也就是说,对于Merkle树中的每个令牌,只有一个“位置”将该令牌用于允许交易的“地方”。 这种格式允许用户检查等离子链的完整历史记录,以及证明和反对特定令牌的所有权。
为了花费令牌,您需要验证链,检查丢失的区块,然后再重新签名事务以及整个历史记录。
该块如下:
const blockFields = [ {name: 'prevHash'}, {name: 'blockNum', isDecimal: true}, {name: 'transactions'}, {name: 'merkleRoot'}, {name: 'time'} ]
从根本上讲,区块链只是一个链块,并具有到前一个链块的链接。 这种结构使得有可能获得不变性,即不重写历史。 merkleRoot使将检查点写入根链成为可能。
在根链中,在智能合约级别,它看起来像这样(Solidity语言):
/* * Block structure (represents one block in a chain) */ struct Block { uint block_num; bytes32 merkle_root; uint time; /* * Transaction structure (decoded from RLP form) */ struct Transaction { bytes32 prevhash; uint prev_block; uint token_id; address new_owner; }
使用编码/解码-RLP序列化/反序列化功能执行编码。
进入等离子现金的方式
任何人都可以简单地通过将以太币转移到智能合约来将资金存入Plasma Cash。 结果,将在特定的tokenId位置接收OPP令牌。
这是Solidity中的实现:
function deposit() public payable { uint token_id = uint(keccak256(msg.sender, msg.value, deposit_blk)); // token.index = deposit_blk; tokens[token_id] = msg.value; deposit_blk += 1; emit DepositAdded(msg.sender, msg.value, token_id, current_blk); }
即,tokenId被生成为随机数(哈希)。 接下来,将生成一个事件,该事件将在子链中进行扫描。
提取等离子现金的方法
每个人都可以通过提供令牌所有权历史记录中的最后两项交易来提取其令牌。
从根链退出的实现:
function startExit(uint block_num, bytes tx1, bytes tx0, bytes proof1, bytes proof0) public returns (uint exit_id) { require(checkPatriciaProof(keccak256(tx1), childChain[block_num].merkle_root, proof1)); bytes32 prev_hash; uint prev_blk; uint token_id; address new_owner; (prev_hash, prev_blk, token_id, new_owner,) = getTransactionFromRLP(tx1); require(msg.sender == new_owner); require(tokens[token_id] > 0); bytes32 hashPrevTx = keccak256(tx0); require(checkPatriciaProof(hashPrevTx, childChain[prev_blk].merkle_root, proof0)); require(prev_hash == hashPrevTx); Exit storage record = exitRecords[token_id]; require(record.block_num == 0); record.block_num = block_num; record.new_owner = msg.sender; record.prev_block = prev_blk; if (childChain[block_num].time > block.timestamp - week) record.priority = childChain[block_num].time; else record.priority = block.timestamp - week; exits.add(record.priority); exit_ids[record.priority].push(token_id); emit ExitAdded(msg.sender, record.priority, token_id); return token_id; }
首先,检查两个事务。 如果当前用户是交易的所有者,那么我们只需将其输出添加到结构中,并留出两周的时间来挑战输出。
该结论可以通过以下三种方式来质疑:
function challengeSpent(uint exit_id, uint blk_num, bytes tx1, bytes proof) public { require(checkPatriciaProof(keccak256(tx1), childChain[blk_num].merkle_root, proof)); Exit memory record = exitRecords[exit_id]; require(record.block_num > 0); uint prev_block; uint token_id; (, prev_block , token_id, ) = getTransactionFromRLP(tx1); require(tokens[token_id] > 0); require(prev_block == record.block_num && record.block_num < blk_num); require(token_id == exit_id); exit_ids[record.priority].remove(exit_id); delete exitRecords[exit_id]; emit ExitChallengedEvent(exit_id); }
如果有一项交易已经在使用显示的令牌,那么这种提款将被取消!
/* * Challenge exit by providing * a proof of a transaction spending P(C) that appears before C */ function challengeDoubleSpend(uint exit_id, uint blk_num, bytes tx1, bytes proof) public { require(checkPatriciaProof(keccak256(tx1), childChain[blk_num].merkle_root, proof)); Exit memory record = exitRecords[exit_id]; require(record.block_num > 0); // bytes32 prev_hash; uint prev_block; uint token_id; (, prev_block , token_id, ) = getTransactionFromRLP(tx1); require(tokens[token_id] > 0); // check if token double spent require(prev_block == record.prev_block && blk_num < record.block_num); // require(token_id == exit_id); exit_ids[record.priority].remove(exit_id); delete exitRecords[exit_id]; emit ExitChallengedEvent(exit_id); }
这与在提取之前已花费令牌上的支票相同。 首先,检查根哈希中的事务。 接下来,如果输出已经用完,我们将其删除。
这可能是一个错误的故事,因此您需要通过子交易进行确认:
// */ function challengeInvalidHistory(uint exit_id, uint blk_num, bytes tx0, bytes proof) public { // check if proof is valid require(checkPatriciaProof(keccak256(tx0), childChain[blk_num].merkle_root, proof)); Exit memory record = exitRecords[exit_id]; require(record.block_num > 0); bytes32 prev_hash; uint token_id; (prev_hash, , token_id, ) = getTransactionFromRLP(tx0); //require(exit_id == token_id); require(tokens[token_id] > 0); // transaction should be before exit tx in history require(blk_num < record.block_num - 1); challenged[exit_id] = blk_num; emit ChallengedInvalidHistory(exit_id, token_id); }
调用第一个和第二个脚本会立即阻止输出。
可以通过提供直接后代来应答对第三种情况的调用。 它必须等于或早于父事务。
/* * Respond to invalid history challenge by providing * the direct child of C*, which must be either equal to or before P( C ) */ function respondChallenge(uint exit_id, uint blk_num, bytes childtx, bytes proof) public { require(challenged[exit_id] > 0); Exit memory record = exitRecords[exit_id]; require(record.block_num > 0); require(checkPatriciaProof(keccak256(childtx), childChain[blk_num].merkle_root, proof)); // get transaction from rlpencoded form bytes32 prev_hash; uint prev_block; uint token_id; (prev_hash, prev_block, token_id, ) = getTransactionFromRLP(childtx); // if direct child if (prev_block == challenged[exit_id] ) { if (blk_num <= record.prev_block && token_id == exit_id ) { delete challenged[exit_id]; emit ExitRespondedEvent(exit_id); } else { exit_ids[record.priority].remove(exit_id); delete exitRecords[exit_id]; emit ExitChallengedEvent(exit_id); } } }
也就是说,如果接收到正确的子事务,则输出有争议,并保留在队列中!
构建了机会血浆现金协议的一部分后,得出以下结论:
该协议通过以太坊根链提供安全性。
通过使根链和状态压缩(事务块)的输入和输出过程复杂化,我们检查了根链的所有输出和输入方法,还研究了基本数据结构:事务和块。
使用基于以太坊网络的侧链,可以显着加快交易速度。 机会由一个操作员每秒最多接收
300,000个事务。 这远远超过当前的支付系统所能提供的。
尽管存在数据可用性方面的问题,但运营商仍提供了区块链的高度稳定性,并使其能够进行有效的国际业务交易。
Plasma Cash带来了可扩展性的巨大增长。 因此,Opporty使用等离子作为其PoE协议的一部分。
有用的链接
- 白皮书等离子
- Git中心
- 用例和架构描述
- 闪电网纸