为什么原子交换不好,渠道将如何帮助原子交换,君士坦丁堡硬叉发生了什么重要的事情,以及什么也没钱买汽油时该怎么办。
任何安全专业人员的主要动机是希望避免责任。
普罗维登斯很客气,我离开了ICO,不等待第一次不可逆转的交易,而是很快发现自己处于加密货币交易所发展的背后。
我绝对不是Malchish Kibalchish,而且严格的外观足以让我通过所有密钥和密码。 因此,作为一名架构师,我的主要目标是使密码分析的热点远离我所钟爱的基础架构元素。
不是你的钥匙,不是你的问题
我们正在建立资产交换系统,并希望在家里排除这些资产的中间存储,但是我们必须确保交易的安全性。
您可以在有争议的情况下担任法官,并使用需要三个签名中的两个签名的钱包进行交易:买方,卖方和代管。
但是,如果参与者成功攻击了第三方托管,则他将收到所需的两个签名。
原子交换是一种交换方案,其中智能合约充当担保人,仅允许诚实的行为。
就像在关于狼山羊和卷心菜的谜语中一样,您只能根据唯一正确的情况采取行动,而退后一步则蒙受损失。
该命令不仅提供了无用的动物,还提供了哈希函数,该函数难以找到碰撞,因此不值得开始。
第一步:谜语
假设爱丽丝想在一个美好的早晨将比特币交给鲍勃,以换取几笔“加密货币”。
- 她做了一个大秘密
- 从中接收哈希
- 它将比特币转移到智能合约中,鲍勃可以通过出示机密从中获利(币值必须与合约中指定的相同)
- 如果鲍勃晚上不去看他的比特币,爱丽丝可以把它们找回来。
第二步:诱饵
鲍勃(Bob)进入游戏并将“ cryptoeuro”转移到他的合同中,该合同的写法是:
- 爱丽丝可以通过提供一个秘密号码来领取“加密货币”
- 不早于午餐,如果未出现爱丽丝,鲍勃可以退还押金
第三步:诱饵中的解决方案
爱丽丝为钱而来,并从鲍勃的合同中拿了钱,同时透露了她的秘密。
最后一步:谜题解决
鲍勃(Bob)看到了这笔交易,他的凝神凝视着眼神,将爱丽丝(Alice)向合同提出的秘密与她隔离了。 他使用这个秘密来收集他的比特币。
当出现问题时
如果爱丽丝突然变成了凡人,鲍勃就拿他的元钱吃午饭。
反过来,如果诡Bob的鲍勃(Bob)决定将这笔钱保留到更好的时间,那么晚上的爱丽丝会返回比特币。
如果您喜欢图片而不是文字,那么在哈布雷(Habré)上,
将为您提供有关原子交换工作的更详细和清晰的
说明 。
超时之间的差异是为了确保我们免受恶意的爱丽丝(Alice)的侵害,后者在最后一刻就拿走了鲍勃(Bob)的钱,而且超时时间到了,他用颤抖的手指将十六进制驱动到交易中。
参加者不能赔钱,最高将不得不等待退款。
区块链支持这是一个简单的方案,例如毡靴,它不需要交互的区块链:
- 支持至少一个分支机构的智能合约
- 两个区块链必须支持相同的哈希算法(不要忘记检查密码的长度)
- 时间锁。
乍一看,人们已经可以和交易所说“再见,我们的会议是个错误”,但是当时还没有。
尽管具有所有优点,但原子交换解决方案并不具有流动性。 很大程度上是因为在最受欢迎的一对BTC-USD中,法定货币部分并未被完全标记。
USDT的成功产生了各种形式的ERC20格式的稳定币,从保管USDC到算法最丰富的DAI都可以使用。
因此,为简单起见,我们进一步争辩说,爱丽丝将Bobcoins出售给Bob以获得一些ERC20代币,并且我们希望稳定器获得成功,因为我们还有许多技术问题。
速度
仅比特币和以太坊并不太快,但是在这里我们必须首先等待一次包含所有确认的存款,然后再等待第二次。
这是因为知道秘密的参与者首先赚钱,而对手等待决赛,然后才转移他的部分。
此外,我们正在处理非常不稳定的资产,因此在此期间,过程可能会发生重大变化,而且更改条件也不容易。
机密性
任何交换都会在两个区块链上留下工件。 细心的观察者可以注意到智能合约中的相同哈希值,并得出在此已达成协议的合乎逻辑的结论,从中可以得出从汇率到税收的许多结论。
当交易所知道您的事务时-这是非常不愉快的,当每个人都知道它时-这是双重令人不愉快的。
易用性
一般而言,区块链马尤其是以太坊。 让我们看看买卖双方将要进行的身体动作。
从卖方的角度来看,一切都相对简单:您只需要将比特币转移到p2sh地址即可。 有了以太,一切都变得更加棘手。
合同考虑一个千兆比特平均交换合同:
contract iERC20 { function totalSupply() public view returns (uint256); function transfer(address receiver, uint numTokens) public returns (bool); function balanceOf(address tokenOwner) public view returns (uint); function approve(address delegate, uint numTokens) public returns (bool); function allowance(address owner, address delegate) public view returns (uint); function transferFrom(address owner, address buyer, uint numTokens) public returns (bool); } contract Swapper { struct Swap { iERC20 token; bytes32 hash; uint amount; uint refundTime; bytes32 secret; } mapping (address => mapping(address => Swap)) swaps; function create(iERC20 token, bytes32 hash, address receiver, uint amount, uint refundTime) public { require(swaps[msg.sender][receiver].amount == 0); // check is swap with given hash already exists require(token.transferFrom(msg.sender, address(this), amount)); // transfer locked tokens to swap contract swaps[msg.sender][receiver] = Swap(token, hash, amount, refundTime, 0x00); //create swap } function hashOf(bytes32 secret) public pure returns(bytes32) { return sha256(abi.encodePacked(secret)); } function withdraw(address owner, bytes32 secret) public { Swap memory swap = swaps[owner][msg.sender]; require(swap.secret == bytes32(0)); require(swap.hash == sha256(abi.encodePacked(secret))); // swap exists swaps[owner][msg.sender].secret = secret; swap.token.transfer(msg.sender, swap.amount); } function refund(address receiver) public { Swap memory swap = swaps[msg.sender][receiver]; require(now > swap.refundTime); delete swaps[msg.sender][receiver]; swap.token.transfer(msg.sender, swap.amount); } }
注意! 不要使用有关生产的文章中的此合同和其他合同,它们仅用于演示。
特别是这个 。
- 鲍勃必须在令牌合约上调用
approve
方法,以使交换合约可以访问其令牌
- 鲍勃使用
transferFrom
方法创建交换和合同,将发件人令牌带到他的地址
- 爱丽丝在
withdraw
透露秘密与合同通话transfer
大多数钱包和
approve
都不支持
approve
令牌,这是有充分理由的。
用户本身经常会犯错,只是将令牌转移到合同中,之后令牌便会丢失。 对Etherscan的评论充满了悲惨的悲哀。
要签订合同,您需要以ETH支付佣金,因此双方参与者都必须在交易开始前就对他们进行库存,并且很少有人愿意这样做。
气嘴
首先,有必要尽可能删除发件人的支票,并假设我们有某人遭受过剩的汽油之苦并与所有人订立合同。
升级合同 contract Swapper { struct Swap { iERC20 token; address receiver; uint amount; address refundAddress; uint refundTime; } mapping (bytes32 => Swap) swaps; function create(iERC20 token, bytes32 hash, address receiver, uint amount, address refundAddress, uint refundTime) public { require(swaps[hash].amount == 0); // use hash once require(token.transferFrom(msg.sender, address(this), amount)); swaps[hash] = Swap(token, receiver, amount, refundAddress, refundTime); } function withdraw(bytes memory secret) public { bytes32 hash = sha256(secret); Swap memory swap = swaps[hash]; require(swap.amount > 0); delete swaps[hash]; swap.token.transfer(swap.receiver, swap.amount); } function refund(bytes32 hash) public { Swap memory swap = swaps[hash]; require(now > swap.refundTime); delete swaps[hash]; swap.token.transfer(swap.refundAddress, swap.amount); } }
合同密钥二元论和EIP 712
众所周知,广播中的地址可以是合同,也可以是主题,换句话说,就是钥匙。
密钥的主要用途是对任何消息进行签名。
在检查Bob密钥的签名之前,我们可以使用Bob合同作为发件人,它进行所有必要的传递。
现在,任何人都可以赞助会员的佣金,但只有知道钥匙的人才能做出决定。
鲍勃合同 library EIP712ProxyLibrary { function hashCommand(address sender, iERC20 token, Swapper swapper, bytes32 hash, address receiver, uint amount, address refundAddress, uint refundTime) public view returns(bytes32); } contract ProxyBob { address owner; constructor(address _owner) public { owner = _owner; } function createSwap(Swapper swapper, iERC20 token, bytes32 hash, address receiver, uint amount, address refundAddress, uint refundTime, uint8 v, bytes32 r, bytes32 s) public { require(owner == ecrecover(EIP712ProxyLibrary.hashCommand(address(this), token, swapper, hash, receiver, amount, refundAddress, refundTime), v, r, s)); token.approve(address(swapper), amount); swapper.create(token, hash, receiver, amount, refundAddress, refundTime); } }
以太坊有一个
EIP 712标准,用于处理复杂数据结构的签名,您可以在
Metamask钱包博客中了解更多信息
。分而治之
通常,入侵以太坊合约的情形如下所示:
- 参与者向合同支付资金
- 然后拿钱
- 出问题了
- 攻击者一次又一次地取钱
如果我们回到第一个示例,那么如果谜语是一个空字节集,就会出问题。
如何偷百万创建带有哈希值的交换0x66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925
这是来自0x0000000000000000000000000000000000000000000000000000000000000000
sha256
我们传递秘密并收集令牌
我们再次传递它并带走陌生人,都是因为0 = 0
通过为每个交易创建单独的合约,我们可以在EVM级别隔离合约。
但这还不是全部:现在每笔交易都有自己的地址,您可以从任何钱包或交易所将令牌转移到该地址。
放弃合同并创建2
但是现在,对于每笔交易,我们都必须创建合同并等待买方将劳动力“加密”转移到那里。 在“早上合约,晚上花钱”的计划中,总是有买方会掉下来的危险,而以太已经被用来建立合约了。
早上可以赚钱,晚上可以赚钱吗?
在君士坦丁堡硬叉中,
EIP 1014开发人员添加了create2语句,该语句在确定性地址处创建新合同
keccak256( 0xff ++ address ++ salt ++ keccak256(init_code))[12:]
哪里
- 地址-工厂合同地址
- 盐-一些数字,其含义将在下一个系列中学习
- init_code-合同字节码和构造函数参数。
工厂该说明仅通过组装起作用,因此工厂看上去有些恐惧:
contract Factory { event Deployed(address addr, uint256 salt); function create2(bytes memory code, uint256 salt) public { address addr; assembly { addr := create2(0, add(code, 0x20), mload(code), salt) } emit Deployed(addr, salt); } }
您的合同代码可以使用web3获得:
const MyContract = new web3.eth.Contract(ABI, {}) const ode = MyContract.deploy({ data: BYTECODE, arguments: contructorArgs }).encodeABI(); const factory = new web3.eth.Contract(FACTORY_ABI, factoryAddress); tx = factory.methods.create2(ode, salt);
由于对固体的支持有限,由于醚的某些微妙之处,合同的天然气可能无法正确计算。
特别好的是,如果天然气短缺,合同会因内部错误而下跌,而不会像预期的那样通知没有足够的天然气。
现在,我们无需预先创建令牌就可以将令牌转移到合同中,并且在我们将令牌发布到网络上之前,没有人会猜测合同的确切功能。
乌鸦不会啄乌鸦
显然,这样一个孩子的骗术不会阻止一位真正的分析师,特别是那些在打击洗钱
制度的
敌人方面获得了良好投资的分析师,并且在缔结合同后,他仍然会看到混乱。
如何确保哈希不点亮?
我们将掉期本身转移到链上:参与者交换签名以转移到掉期合同中,然后秘密公开。
一步一步创建两个“ multisig”,如果您具有Alice和Bob的签名,则可以从中提取资金。
为了脱机,其中一位参与者没有成为悲剧,我们添加了良好的旧超时时间。
爱丽丝和鲍勃并行存款
- 爱丽丝(Alice)制作了一个秘密,并向鲍勃(Bob)提供了秘密的哈希值和交易签名,从而将比特币转移到交换地址
- 鲍勃(Bob)为艾丽丝(Alice)在交换合同上撤回带有隐藏哈希值的令牌的签名。
- 爱丽丝告诉鲍勃这个秘密。
此时此刻,和谐相处:爱丽丝和鲍勃都可以随时完成交易。 在这种友好的环境中,他们可以交换签名以将钱提取到最终地址。
对于外部观察者来说,这笔钱看起来像是像一张带有2个多重签名的合同。
而且,由于所有确认之后都已构成了秘密,因此这种方案还允许双方同时进行存款。
2级
由于我们可以将钱提取到一个地址而无需发布中间交易,因此没有什么可以阻止我们将钱提取到多个地址并进行无限数量的中间交易。 这并不是交换所必需的,但如果您开始收集交换,就很难停止。
现在,爱丽丝和鲍勃将能够与强大和主要。 例如,通过每秒交换Satoshi来自动计算平均价格,或者直接将做市商和流动性接受者联系起来。
一步一步- 卖方提供了一个秘密,并给买方提供了一个秘密和交易签名的哈希,其中部分资金转移到了p2sh掉期地址,其余的则退还给了卖方的地址。
- 买方发送一个签名,允许在掉期时提取令牌并将其交付到收件人的地址。
- 卖方揭示了一个秘密
- 故事用一个新的秘密重复进行,同时在掉期和投降中添加了先前购买的输出到买方的地址,并已经支付给卖方的地址
现在我们可以进行高速p2p交易,主要是监视时间并在超时之前完成交易。
但是,在略微调整了合同之后,我们可以使渠道永生,这将大大简化我们的网络创建。
但是我们将在下一个系列中讨论这一点。