我充分尊重你和我交互的權(quán)力慰技,但你與我的每次交互都將會收費(fèi)为黎。
---以太坊
0x01 什么是微支付通道
以太交易為資產(chǎn)的流動提供了一種比較安全可靠的方式擦耀,但以太坊中每筆交易都需要被包到一個(gè)區(qū)塊中并通過礦工挖礦的方式進(jìn)行全網(wǎng)共識排惨,以使該交易有效。 這意味著每筆交易幌氮,無論交易所代表資產(chǎn)的多少擂找,都需要一些時(shí)間并支付給礦工一定的費(fèi)用。 這無疑會對在微支付場景中使用以太坊構(gòu)成不小的障礙浩销,可以想象一下贯涎,你愿意為了買包鹽進(jìn)行跨行轉(zhuǎn)賬么?(法幣的跨行轉(zhuǎn)賬需要等待一定的時(shí)間慢洋,并且很多時(shí)候都要手續(xù)費(fèi)惫确,這點(diǎn)兒和目前的區(qū)塊鏈交易有點(diǎn)兒類似)
那么席函,有沒有一種類似支票的一種支付方式呢?我如果要付錢,給對方先開個(gè)條子今野,對方拿著條子去取錢就好了舆吮。這就是微支付通道的基本原理辞嗡,它允許交易雙方在鏈下進(jìn)行多次交易魔策,只需要最后結(jié)算的時(shí)候與以太坊進(jìn)行交互即可酸员。通過這種方式,就避免了一些無關(guān)緊要的等待和交易費(fèi)用讳嘱。
具體怎么做呢幔嗦?最簡單的微支付通道分三個(gè)步驟進(jìn)行交易:
- 要付錢的人部署一個(gè)智能合約,將自己的錢轉(zhuǎn)到合約里沥潭,相當(dāng)于打開了一個(gè)支付通道邀泉。
- 付錢的時(shí)候,付款人發(fā)送一個(gè)帶自己簽名的消息給收款人钝鸽,指明自己欠收款人多少錢汇恤。
- 收款人關(guān)閉支付通道,通過將上面第二步收到的消息發(fā)送給智能合約以取出屬于自己的那部分錢拔恰,并將剩余的錢退還給付款人因谎。
這里面的關(guān)鍵點(diǎn)是,第一步和第三步是需要與以太坊進(jìn)行鏈上交互的颜懊,第二步是可以反復(fù)在鏈下進(jìn)行的财岔,付款人可以通過不同的方式比如郵件,微信等等將付款消息發(fā)送給收款人都不妨事饭冬。
你可能還是會有各種疑問,比如付款人在收款人之前把錢取走了怎么辦揪阶?付款消息被別人截取是不是也可以拿去取錢了昌抠?收款人遲遲不取錢怎么辦?莫急鲁僚,且聽我慢慢道來炊苫。
0x02 打開支付通道
部署一個(gè)合約,并把錢轉(zhuǎn)進(jìn)去就好了冰沙。下面是最簡單微支付通道合約的一部分侨艾,包含了打開支付通道所需最主要的數(shù)據(jù)。
contract SimplePaymentChannel {
address public sender; // 付款人賬戶拓挥,指定付款人唠梨,對簽名進(jìn)行驗(yàn)證
address public recipient; // 收款人賬戶,指定收款人侥啤,不怕消息攔截
uint256 public expiration; // 支付通道存在的時(shí)間当叭,防止收款人太長時(shí)間不取款.
// payable 的構(gòu)造函數(shù),部署合約的同時(shí)可以把以太幣打進(jìn)來了
function SimplePaymentChannel(address _recipient, uint256 duration)
public
payable
{
sender = msg.sender;
recipient = _recipient;
expiration = now + duration;
}
0x03 付款
付款人通過向收款人發(fā)送簽名消息的方式來支付費(fèi)用盖灸。此步驟完全在鏈下進(jìn)行蚁鳖,每條消息主要包含下面的內(nèi)容:
- 當(dāng)前所用支付通道合約地址。
- 到目前為止應(yīng)付給收款人的總金額赁炎。
怎么沒有收款人地址呢醉箕?因?yàn)橥ǖ篮霞s里已經(jīng)包含收款人地址啦。
為啥是總金額呢?因?yàn)檫@樣就可以一次交易取出所有錢啦讥裤,要么一筆一筆的取又要耗不少交易手續(xù)費(fèi)放棒。
0x04 核實(shí)付款
由于支付通道中的錢很多情況下不會被立馬取出,收款人對支付消息的驗(yàn)證就非常重要坞琴,否則哨查,拿到空頭支票就不好了。
收款人一般都要在下面幾個(gè)方面對付款消息進(jìn)行驗(yàn)證:
- 驗(yàn)證消息中的支付通道地址是否正確剧辐。
- 驗(yàn)證付款總金額是否正確寒亥。
- 驗(yàn)證新的付款總金額是否超出了支付通道合約中的以太幣金額。
- 驗(yàn)證簽名有效性荧关,保證消息確實(shí)是從付款人那里發(fā)出的溉奕。
0x05 關(guān)閉支付通道
當(dāng)收款人準(zhǔn)備好取出他們的資金時(shí),就可以通過調(diào)用通道合約上的 close 函數(shù)來關(guān)閉支付通道了忍啤。 關(guān)閉這個(gè)通道可以取出屬于收款人的那部分資金加勤,然后毀掉合同,把剩下的緊張發(fā)回給付款人同波。 若要關(guān)閉通道鳄梅,收款人需要發(fā)送由付款人簽名的消息到通道合約,由通道合約對消息進(jìn)行驗(yàn)證并執(zhí)行相應(yīng)操作未檩。
function isValidSignature(uint256 amount, bytes signature)
internal
view
returns (bool)
{
bytes32 message = prefixed(keccak256(this, amount));
// 驗(yàn)證簽名是來自于付款人
return recoverSigner(message, signature) == sender;
}
// 收款人可以在任何時(shí)候通過提供由付款人發(fā)來的簽名消息來關(guān)閉通道戴尸。收款人會收到簽名消息中包含的金額,合約中剩余的部分會被發(fā)送給部署合約的付款人冤狡。
function close(uint256 amount, bytes signature) public {
require(msg.sender == recipient);
require(isValidSignature(amount, signature));
recipient.transfer(amount);
selfdestruct(sender);
}
注意這里的 close 函數(shù)只能由收款人發(fā)起調(diào)用孙蒙,收款人非常有動力提供最新的付款消息,因?yàn)樽钚碌母犊钕⒗锖凶疃嗟那房羁傤~悲雳。如果允許付款人調(diào)用這個(gè)函數(shù)挎峦,付款人肯定更傾向于提供最老的付款信息,因?yàn)樗俗钚〉那房羁傤~合瓢。
0x06 總結(jié)
現(xiàn)在大家日子都不太好過坦胶,手續(xù)費(fèi)能省點(diǎn)兒是點(diǎn)兒吧。本文簡單介紹了以太坊微支付通道的原理晴楔,寫的比較倉促迁央,有不清楚的地方,歡迎給我留言滥崩,我抽空再給補(bǔ)上岖圈。