您好,登錄后才能下訂單哦!
本篇內容主要講解“以太坊閃電網絡實現原理是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“以太坊閃電網絡實現原理是什么”吧!
線上直接轉賬需要一定的費用,如果存在大量小額交易的情況下,費用會變的難以承受,因而以太坊引入了微交易支付通道來解決這個問題。以太坊提供了一個票據支付方案,主要依賴于智能合約實現的一對多的賬單系統。該賬單系統大致上的執行流程如下.
1:賬單生成,同時提供機制往賬單上存入保證金。
2:交易發起人生成交易票據
3:直接將票據發送給接收人
4:接收人兌現票據,從合約轉賬(盡管某次兌現可能會失敗,但是只要票據存在最終還是能夠兌現).
這種交易優點在于可以在線下發送任意數量的交易,而只需要兩個鏈上交易(存入保證金,兌現)只要存入保證金,線下通過交換票據進行任意數量的交易,避免了頻繁的線上轉賬,節省了交易費用。
. ├── api.go //對外接口 ├── cheque.go //賬單 ├── cheque_test.go ├── contract │ ├── chequebook.go //合約go語言接口 │ ├── chequebook.sol //合約源碼 │ ├── code.go //合約byte碼 │ ├── mortal.sol //合約銷毀 │ └── owned.sol //hebe權限 └── gencode.go //合約byte碼生成
合約自身是接收轉賬的,用戶可以在初始化或者后來增加金額,可以通過cash方法兌現票據,轉賬金額都會保存在send變量上。
pragma solidity ^0.4.18; import "./mortal.sol"; /// @title Chequebook for Ethereum micropayments /// @author Daniel A. Nagy <daniel@ethereum.org> contract chequebook is mortal { // Cumulative paid amount in wei to each beneficiary //已經支付的 可以控制雙花,防止多次兌換票據 mapping (address => uint256) public sent; /// @notice Overdraft event event Overdraft(address deadbeat); // Allow sending ether to the chequebook. function() public payable { } /// @notice Cash cheque /// /// @param beneficiary beneficiary address /// @param amount cumulative amount in wei /// @param sig_v signature parameter v /// @param sig_r signature parameter r /// @param sig_s signature parameter s /// The digital signature is calculated on the concatenated triplet of contract address, beneficiary address and cumulative amount function cash(address beneficiary, uint256 amount, uint8 sig_v, bytes32 sig_r, bytes32 sig_s) public { // Check if the cheque is old. // Only cheques that are more recent than the last cashed one are considered. require(amount > sent[beneficiary]); // Check the digital signature of the cheque. bytes32 hash = keccak256(address(this), beneficiary, amount); require(owner == ecrecover(hash, sig_v, sig_r, sig_s)); // Attempt sending the difference between the cumulative amount on the cheque // and the cumulative amount on the last cashed cheque to beneficiary. uint256 diff = amount - sent[beneficiary]; if (diff <= this.balance) { // update the cumulative amount before sending sent[beneficiary] = amount; beneficiary.transfer(diff); } else { // Upon failure, punish owner for writing a bounced cheque. // owner.sendToDebtorsPrison(); Overdraft(owner); // Compensate beneficiary. selfdestruct(beneficiary); } } }
賬單保存了賬本的位置,記賬人,所有人等信息。
// Chequebook can create and sign cheques from a single contract to multiple beneficiaries. // It is the outgoing payment handler for peer to peer micropayments. type Chequebook struct { path string // path to chequebook file prvKey *ecdsa.PrivateKey // private key to sign cheque with lock sync.Mutex // backend Backend // blockchain API quit chan bool // when closed causes autodeposit to stop owner common.Address // owner address (derived from pubkey) contract *contract.Chequebook // abigen binding session *contract.ChequebookSession // abigen binding with Tx Opts // persisted fields balance *big.Int // not synced with blockchain contractAddr common.Address // contract address sent map[common.Address]*big.Int //tallies for beneficiaries txhash string // tx hash of last deposit tx threshold *big.Int // threshold that triggers autodeposit if not nil buffer *big.Int // buffer to keep on top of balance for fork protection log log.Logger // contextual logger with the contract address embedded }
票據:合約位置,接收人,金額,簽名
type Cheque struct { Contract common.Address // address of chequebook, needed to avoid cross-contract submission Beneficiary common.Address Amount *big.Int // cumulative amount of all funds sent Sig []byte // signature Sign(Keccak256(contract, beneficiary, amount), prvKey) }
生成一條支付記錄,返回一份簽名后的票據,收費這憑借這張票據從合約里面取錢.
// Issue creates a cheque signed by the chequebook owner's private key. The // signer commits to a contract (one that they own), a beneficiary and amount. func (self *Chequebook) Issue(beneficiary common.Address, amount *big.Int) (ch *Cheque, err error) { defer self.lock.Unlock() self.lock.Lock() if amount.Sign() <= 0 { return nil, fmt.Errorf("amount must be greater than zero (%v)", amount) } if self.balance.Cmp(amount) < 0 { err = fmt.Errorf("insufficient funds to issue cheque for amount: %v. balance: %v", amount, self.balance) } else { var sig []byte sent, found := self.sent[beneficiary] if !found { sent = new(big.Int) self.sent[beneficiary] = sent } sum := new(big.Int).Set(sent) sum.Add(sum, amount) sig, err = crypto.Sign(sigHash(self.contractAddr, beneficiary, sum), self.prvKey) if err == nil { ch = &Cheque{ Contract: self.contractAddr, Beneficiary: beneficiary, Amount: sum, Sig: sig, } sent.Set(sum) self.balance.Sub(self.balance, amount) // subtract amount from balance } } // 賬單余額少于閾值,自動補充. if self.threshold != nil { if self.balance.Cmp(self.threshold) < 0 { send := new(big.Int).Sub(self.buffer, self.balance) self.deposit(send) } } return }
func (self *Chequebook) Deposit(amount *big.Int) (string, error) { defer self.lock.Unlock() self.lock.Lock() return self.deposit(amount) } func (self *Chequebook) deposit(amount *big.Int) (string, error) { // since the amount is variable here, we do not use sessions depositTransactor := bind.NewKeyedTransactor(self.prvKey) depositTransactor.Value = amount chbookRaw := &contract.ChequebookRaw{Contract: self.contract} //轉入金額 tx, err := chbookRaw.Transfer(depositTransactor) if err != nil { self.log.Warn("Failed to fund chequebook", "amount", amount, "balance", self.balance, "target", self.buffer, "err", err) return "", err } // assume that transaction is actually successful, we add the amount to balance right away self.balance.Add(self.balance, amount) self.log.Trace("Deposited funds to chequebook", "amount", amount, "balance", self.balance, "target", self.buffer) return tx.Hash().Hex(), nil }
// Cash is a convenience method to cash any cheque. func (self *Chequebook) Cash(ch *Cheque) (txhash string, err error) { return ch.Cash(self.session) } // Cash cashes the cheque by sending an Ethereum transaction. func (self *Cheque) Cash(session *contract.ChequebookSession) (string, error) { v, r, s := sig2vrs(self.Sig) //調用合約的cash方法 提取代幣 tx, err := session.Cash(self.Beneficiary, self.Amount, v, r, s) if err != nil { return "", err } return tx.Hash().Hex(), nil }
OutBox:用于在電對點網絡中發行票據,提供了保證金存入,票據發行,自動存入保證金等接口。
type Outbox struct { chequeBook *Chequebook beneficiary common.Address } // Issue creates cheque. func (self *Outbox) Issue(amount *big.Int) (swap.Promise, error) { return self.chequeBook.Issue(self.beneficiary, amount) } // AutoDeposit enables auto-deposits on the underlying chequebook. func (self *Outbox) AutoDeposit(interval time.Duration, threshold, buffer *big.Int) { self.chequeBook.AutoDeposit(interval, threshold, buffer) }
InBox:用于在電對點網絡中票據兌換,提供了直接兌換,定時兌換,延遲兌換的接口功能。
// Inbox can deposit, verify and cash cheques from a single contract to a single // beneficiary. It is the incoming payment handler for peer to peer micropayments. type Inbox struct { lock sync.Mutex contract common.Address // peer's chequebook contract beneficiary common.Address // local peer's receiving address sender common.Address // local peer's address to send cashing tx from signer *ecdsa.PublicKey // peer's public key txhash string // tx hash of last cashing tx session *contract.ChequebookSession // abi contract backend with tx opts quit chan bool // when closed causes autocash to stop maxUncashed *big.Int // threshold that triggers autocashing cashed *big.Int // cumulative amount cashed cheque *Cheque // last cheque, nil if none yet received log log.Logger // contextual logger with the contract address embedded } // Cash attempts to cash the current cheque. func (self *Inbox) Cash() (txhash string, err error) { if self.cheque != nil { txhash, err = self.cheque.Cash(self.session) self.log.Trace("Cashing in chequebook cheque", "amount", self.cheque.Amount, "beneficiary", self.beneficiary) self.cashed = self.cheque.Amount } return }
到此,相信大家對“以太坊閃電網絡實現原理是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。