以太坊中的微支付通道

  • Ashton
  • 更新于 2019-01-28 23:03
  • 阅读 3877

以太坊中的微支付通道

我充分尊重你和我交互的权力,但你与我的每次交互都将会收费。 ---以太坊

0x01 什么是微支付通道

以太交易为资产的流动提供了一种比较安全可靠的方式,但以太坊中每笔交易都需要被包到一个区块中并通过矿工挖矿的方式进行全网共识,以使该交易有效。 这意味着每笔交易,无论交易所代表资产的多少,都需要一些时间并支付给矿工一定的费用。 这无疑会对在微支付场景中使用以太坊构成不小的障碍,可以想象一下,你愿意为了买包盐进行跨行转账么?(法币的跨行转账需要等待一定的时间,并且很多时候都要手续费,这点儿和目前的区块链交易有点儿类似)

那么,有没有一种类似支票的一种支付方式呢?我如果要付钱,给对方先开个条子,对方拿着条子去取钱就好了。这就是微支付通道的基本原理,它允许交易双方在链下进行多次交易,只需要最后结算的时候与以太坊进行交互即可。通过这种方式,就避免了一些无关紧要的等待和交易费用。

具体怎么做呢?最简单的微支付通道分三个步骤进行交易:

  1. 要付钱的人部署一个智能合约,将自己的钱转到合约里,相当于打开了一个支付通道。
  2. 付钱的时候,付款人发送一个带自己签名的消息给收款人,指明自己欠收款人多少钱。
  3. 收款人关闭支付通道,通过将上面第二步收到的消息发送给智能合约以取出属于自己的那部分钱,并将剩余的钱退还给付款人。

微支付通道

这里面的关键点是,第一步和第三步是需要与以太坊进行链上交互的,第二步是可以反复在链下进行的,付款人可以通过不同的方式比如邮件,微信等等将付款消息发送给收款人都不妨事。

你可能还是会有各种疑问,比如付款人在收款人之前把钱取走了怎么办?付款消息被别人截取是不是也可以拿去取钱了?收款人迟迟不取钱怎么办?莫急,且听我慢慢道来。

0x02 打开支付通道

部署一个合约,并把钱转进去就好了。下面是最简单微支付通道合约的一部分,包含了打开支付通道所需最主要的数据。

contract SimplePaymentChannel {
    address public sender;     // 付款人账户,指定付款人,对签名进行验证
    address public recipient;  // 收款人账户,指定收款人,不怕消息拦截
    uint256 public expiration; // 支付通道存在的时间,防止收款人太长时间不取款.

    // payable 的构造函数,部署合约的同时可以把以太币打进来了 
    function SimplePaymentChannel(address _recipient, uint256 duration)
        public
        payable
    {
        sender = msg.sender;
        recipient = _recipient;
        expiration = now + duration;
    }

0x03 付款

付款人通过向收款人发送签名消息的方式来支付费用。此步骤完全在链下进行,每条消息主要包含下面的内容:

  1. 当前所用支付通道合约地址。
  2. 到目前为止应付给收款人的总金额。

怎么没有收款人地址呢?因为通道合约里已经包含收款人地址啦。 为啥是总金额呢?因为这样就可以一次交易取出所有钱啦,要么一笔一笔的取又要耗不少交易手续费。

0x04 核实付款

由于支付通道中的钱很多情况下不会被立马取出,收款人对支付消息的验证就非常重要,否则,拿到空头支票就不好了。 收款人一般都要在下面几个方面对付款消息进行验证:

  1. 验证消息中的支付通道地址是否正确。
  2. 验证付款总金额是否正确。
  3. 验证新的付款总金额是否超出了支付通道合约中的以太币金额。
  4. 验证签名有效性,保证消息确实是从付款人那里发出的。

0x05 关闭支付通道

当收款人准备好取出他们的资金时,就可以通过调用通道合约上的 close 函数来关闭支付通道了。 关闭这个通道可以取出属于收款人的那部分资金,然后毁掉合同,把剩下的紧张发回给付款人。 若要关闭通道,收款人需要发送由付款人签名的消息到通道合约,由通道合约对消息进行验证并执行相应操作。

function isValidSignature(uint256 amount, bytes signature)
    internal
    view
    returns (bool)
{
    bytes32 message = prefixed(keccak256(this, amount));

    // 验证签名是来自于付款人
    return recoverSigner(message, signature) == sender;
}

// 收款人可以在任何时候通过提供由付款人发来的签名消息来关闭通道。收款人会收到签名消息中包含的金额,合约中剩余的部分会被发送给部署合约的付款人。
function close(uint256 amount, bytes signature) public {
    require(msg.sender == recipient);
    require(isValidSignature(amount, signature));

    recipient.transfer(amount);
    selfdestruct(sender);
}

注意这里的 close 函数只能由收款人发起调用,收款人非常有动力提供最新的付款消息,因为最新的付款消息里含有最多的欠款总额。如果允许付款人调用这个函数,付款人肯定更倾向于提供最老的付款信息,因为它包含了最小的欠款总额。

0x06 总结

现在大家日子都不太好过,手续费能省点儿是点儿吧。本文简单介绍了以太坊微支付通道的原理,写的比较仓促,有不清楚的地方,欢迎给我留言,我抽空再给补上。

点赞 0
收藏 0
分享

0 条评论

请先 登录 后评论
Ashton
Ashton
0x53b3...c54F
专注于 EVM 和比特币生态的区块链开发者