通过例子学Solidity[注释翻译]
生活随笔
收集整理的這篇文章主要介紹了
通过例子学Solidity[注释翻译]
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
[官方譯文(2)] 通過例子學Solidity[注釋翻譯]
前
繼續翻譯Solidity的官方文檔, 以此也算是自己的學習[Solidity官方手冊](https://solidity.readthedocs.io/zh/latest/solidity-by-example.html)投票(voting)
下面的合同十分的復雜, 但是的確是展現出了`Solidity`的許多特性. 它實現了一個投票的合約. 當然, 電子投票的主要的問題, 如何給當前的投票人分發票 和 如何保證正常的進行. 在這里我們并不會解決所有的問題, 但是 至少我們將展現如何進行一場自動化進行和完全透明的委托投票主要的思路是是對每一個票創建一個合約, 對每個選項提供一個短的名稱. 合約的創建者 就作為這次投票的主持人(chairperson)將會給與其他獨立地址的投票權利這些賬戶(可投票)的擁有者可以自己投這一票, 或者把自己的票委托(delegate)給他們信任的人在這次投票結束的時候, `winningProposal()` (function)將會返回這個票數最多的人(下面是實例的投票代碼, 翻譯水平有限..保留部分原文翻譯)pragma solidity ^0.4.11;/// @title Voting with delegation. contract Ballot {// This declares a new complex type which will// be used for variables later.// It will represent a single voter.(聲明一個新的class 將會成為一個變量, 會代表其中的一個投票者)struct Voter {uint weight; // weight is accumulated(積累) by delegation(委托)bool voted; // if true, that person already votedaddress delegate; // person delegated to (你所委托的人)uint vote; // index of the voted proposal (投票索引號)}// This is a type for a single proposal. (單個提案類型)struct Proposal {bytes32 name; // short name (up to 32 bytes)uint voteCount; // number of accumulated votes(累計票數)}address public chairperson;// This declares a state variable that// stores a `Voter` struct for each possible address.(這里創建里一個投票者的變量, 用于保存每個投票者的地址)mapping(address => Voter) public voters;// A dynamically-sized array of `Proposal` structs.(一個動態分配的票據結構)Proposal[] public proposals;/// Create a new ballot to choose one of `proposalNames`. (創建一個新的票據來選擇一個提案名稱)function Ballot(bytes32[] proposalNames) {chairperson = msg.sender;voters[chairperson].weight = 1;// For each of the provided proposal names, (每一個選舉人的名字創建單個的選舉對象, 并且添加到數組的尾部)// create a new proposal object and add it// to the end of the array.for (uint i = 0; i < proposalNames.length; i++) {// `Proposal({...})` creates a temporary// Proposal object and `proposals.push(...)`// appends it to the end of `proposals`. (意向人對象`proposal`, 使用proposal.push(), 把意向人壓入)proposals.push(Proposal({name: proposalNames[i],voteCount: 0}));}}// Give `voter` the right to vote on this ballot. (給與投票者投票權益)// May only be called by `chairperson`. (只可能是被支持人所調用)function giveRightToVote(address voter) {// If the argument of `require` evaluates to `false`, (如何請求的值是 false , 這個將會被終結, 并且回滾所有的改變)// it terminates and reverts all changes to// the state and to Ether balances. It is often (如果函數被非法調用, 這將會是個很好的辦法)// a good idea to use this if functions are// called incorrectly. But watch out, this (但是需要注意的是, 這將會消耗當前所有的 gas(在未來可能有所改善))// will currently also consume all provided gas// (this is planned to change in the future).require((msg.sender == chairperson) && !voters[voter].voted && (voters[voter].weight == 0));voters[voter].weight = 1;}/// Delegate your vote to the voter `to`. (委托你的票到其他的可信投票者)function delegate(address to) {// assigns referenceVoter storage sender = voters[msg.sender];require(!sender.voted); (這里保證是沒有投過票的)// Self-delegation is not allowed. (不允許自己投給自己)require(to != msg.sender);// Forward the delegation as long as// `to` also delegated.// In general, such loops are very dangerous,// because if they run too long, they might// need more gas than is available in a block.// In this case, the delegation will not be executed,// but in other situations, such loops might// cause a contract to get "stuck" completely.(這里避免一個循環委托的可能性 , 如果A委托給B, B委托給其他人,最終到了A )while (voters[to].delegate != address(0)) {to = voters[to].delegate;// We found a loop in the delegation, not allowed.require(to != msg.sender);}// Since `sender` is a reference, this// modifies `voters[msg.sender].voted`sender.voted = true;sender.delegate = to;Voter storage delegate = voters[to];if (delegate.voted) {// If the delegate already voted, (如果委托投票已經投過, 直接修改票數)// directly add to the number of votesproposals[delegate.vote].voteCount += sender.weight; (投票權重)} else {// If the delegate did not vote yet,// add to her weight.delegate.weight += sender.weight;}}/// Give your vote (including votes delegated to you) (投出你的票票)/// to proposal `proposals[proposal].name`.function vote(uint proposal) {Voter storage sender = voters[msg.sender];require(!sender.voted); (require 是新版的語法)sender.voted = true;sender.vote = proposal;// If `proposal` is out of the range of the array,(如果提案超出了索引范圍, 直接回滾所有數據)// this will throw automatically and revert all// changes.proposals[proposal].voteCount += sender.weight;}/// @dev Computes the winning proposal taking all (根據記票找到最終 的勝出者)/// previous votes into account.function winningProposal() constantreturns (uint winningProposal){uint winningVoteCount = 0;for (uint p = 0; p < proposals.length; p++) {if (proposals[p].voteCount > winningVoteCount) {winningVoteCount = proposals[p].voteCount;winningProposal = p;}}}// Calls winningProposal() function to get the index// of the winner contained in the proposals array and then// returns the name of the winnerfunction winnerName() constantreturns (bytes32 winnerName){winnerName = proposals[winningProposal()].name;} }可能的改進
現在如果,需要指派票權到其他的賬戶,參加多個投票,有好的方案嗎?盲拍
這一節,我們將展示在以太上創建一個完整的盲拍合約是多么簡單. 我們從一個所有人都能看到出價的公開拍賣開始,接著擴展合約成為一個在 **拍賣結束以前不能看到實際出價的盲拍**.簡單的公開拍賣 (Simple Open Auction)
通常簡單的公開拍賣合約, 是每個人可以在拍賣期間提出他們的競拍出價。為了實現競拍人和他們競拍內容的綁定,競拍包括發送金額/ether。如果產生了新的最高競拍價,前一個最高價競拍人將會拿回他的錢。在競拍階段結束后,受益人人需要手動調用合約收取他的錢 (合約不會激活自己. )(合約是存在的函數,需要用戶去調用它 , 他是不能調用自己的)pragma solidity ^0.4.11;contract SimpleAuction {// Parameters of the auction. Times are either (拍賣參數)// absolute unix timestamps (seconds since 1970-01-01) (自unix時間戳的絕對時間)// or time periods in seconds.address public beneficiary;uint public auctionStart;uint public biddingTime;// Current state of the auction. (當前的拍賣狀態)address public highestBidder;uint public highestBid;// Allowed withdrawals of previous bids (可以撤出之前的投標)mapping(address => uint) pendingReturns;// Set to true at the end, disallows any change (已經結束就不允許任何改變)bool ended;// Events that will be fired on changes. (當有了改變的時候, 事件將會被觸發)event HighestBidIncreased(address bidder, uint amount); (到了最高標)event AuctionEnded(address winner, uint amount); (結束)// The following is a so-called natspec comment,// recognizable by the three slashes. (三個斜杠(slash) 的注釋是一個 natspec 的注釋)// It will be shown when the user is asked to// confirm a transaction./// Create a simple auction with `_biddingTime` (競拍時間)/// seconds bidding time on behalf of the/// beneficiary address `_beneficiary`. (實際競拍者賬戶) (_是private的變量(約定習慣))function SimpleAuction(uint _biddingTime,address _beneficiary) {beneficiary = _beneficiary;auctionStart = now;biddingTime = _biddingTime;}/// Bid on the auction with the value sent (對拍賣的競拍金會隨著交易事務一起發送,)/// together with this transaction./// The value will only be refunded if the (只有沒有拍得的時候, 金額才會被退回)/// auction is not won.function bid(出價)() payable {// No arguments are necessary, all (不需要參數, 數據是交易的一部分)// information is already part of// the transaction. The keyword payable// is required for the function to// be able to receive Ether.// Revert the call if the bidding (回滾這個調用, 如果標已經結束)// period is over.require(now <= (auctionStart + biddingTime));// If the bid is not higher, send the// money back.require(msg.value > highestBid); (如果不是最高出價, 那么把保證金返回)if (highestBidder != 0) {// Sending back the money by simply using // highestBidder.send(highestBid) is a security risk(只是用上述函數把幣送回是有個安全隱患)// because it could execute an untrusted contract. (因為可能執行一個 不可信任的合約)// It is always safer to let the recipients// withdraw their money themselves.pendingReturns[highestBidder] += highestBid;}highestBidder = msg.sender;highestBid = msg.value;HighestBidIncreased(msg.sender, msg.value);}/// Withdraw a bid that was overbid. (出價過高的退款)function withdraw() returns (bool) {uint amount = pendingReturns[msg.sender];if (amount > 0) {// It is important to set this to zero because the recipient// can call this function again as part of the receiving call// before `send` returns.pendingReturns[msg.sender] = 0;if (!msg.sender.send(amount)) {// No need to call throw here, just reset the amount owingpendingReturns[msg.sender] = amount;return false;}}return true;}/// End the auction and send the highest bid (結束拍賣,最高者得標)/// to the beneficiary(受惠者).function auctionEnd() {// It is a good guideline to structure functions that interact// with other contracts (i.e. they call functions or send Ether)// into three phases:// 1. checking conditions// 2. performing actions (potentially changing conditions)// 3. interacting with other contracts// If these phases are mixed up, the other contract could call// back into the current contract and modify the state or cause// effects (ether payout) to be performed multiple times.// If functions called internally include interaction with external// contracts, they also have to be considered interaction with// external contracts.// 1. Conditions (當前情況)require(now >= (auctionStart + biddingTime)); // auction did not yet endrequire(!ended); // this function has already been called// 2. Effects (結果)ended = true;AuctionEnded(highestBidder, highestBid); (處理合約中的錢)// 3. Interaction (通知, 交互)beneficiary.transfer(highestBid); (給標)} }盲拍 (Blind Auction )
接下來擴展前面的公開拍賣成為一個盲拍。盲拍的特點是拍賣結束以前沒有時間壓力。在一個透明的計算平臺上創建盲拍系統聽起來可能有些矛盾,但是加密算法能讓你脫離困境。
在拍賣階段, 競拍人不需要發送實際的出價,僅僅只需要發送一個它的散列值。因為目前幾乎不可能找到兩個值(足夠長)的散列值相等,競拍者提交他們的出價散列值。在拍賣結束后,競拍人重新發送未加密的競拍出價,合約將檢查其散列值是否和拍賣階段發送的一樣。 另一個挑戰是如何讓拍賣同時實現綁定和致盲 :防止競拍人競拍成功后不付錢的唯一的辦法是,在競拍出價的同時發送保證金。但是在Ethereum上發送保證金是無法致盲,所有人都能看到保證金。下面的合約通過接受任何盡量大的出價來解決這個問題。當然這可以在最后的揭拍階段進行復核,一些競拍出價可能是無效的,這樣做的目的是(它提供一個顯式的標志指出是無效的競拍,同時包含高額保證金):競拍人可以通過放置幾個無效的高價和低價競拍來混淆競爭對手。
注: 理解上是, 把hash(出價 + 混淆金) 發給合約, 等待競拍結束. 每個人發送自己的 明文出價(cleartext), 之后由合約驗證 , hash(出價+混) 是否等于之前的 hash.contract BlindAuction {struct Bid{bytes32 blindedBid;uint deposit;}address public beneficiary;uint public auctionStart;uint public biddingEnd;uint public revealEnd;bool public ended;mapping(address => Bid[]) public bids;address public highestBidder;uint public highestBid;event AuctionEnded(address winner, uint highestBid);///修飾器(Modifier)是一個簡便的途徑用來驗證函數輸入的有效性。///`onlyBefore` 應用于下面的 `bid`函數,其舊的函數體替換修飾器主體中 `_`后就是其新的函數體modifier onlyBefore(uint _time) { if (now >= _time) throw; _ }modifier onlyAfter(uint _time) { if (now <= _time) throw; _ }function BlindAuction(uint _biddingTime,uint _revealTime,address _beneficiary){beneficiary = _beneficiary;auctionStart = now;biddingEnd = now + _biddingTime;revealEnd = biddingEnd + _revealTime;}///放置一個盲拍出價使用`_blindedBid`=sha3(value,fake,secret).///僅僅在競拍結束正常揭拍后退還發送的以太。當隨同發送的以太至少///等于 "value"指定的保證金并且 "fake"不為true的時候才是有效的競拍///出價。設置 "fake"為true或發送不合適的金額將會掩沒真正的競拍出///價,但是仍然需要抵押保證金。同一個地址可以放置多個競拍。function bid(bytes32 _blindedBid)onlyBefore(biddingEnd){bids[msg.sender].push(Bid({blindedBid: _blindedBid,deposit: msg.value}));}///揭開你的盲拍競價。你將會拿回除了最高出價外的所有競拍保證金///以及正常的無效盲拍保證金。function reveal(uint[] _values, bool[] _fake,bytes32[] _secret)onlyAfter(biddingEnd)onlyBefore(revealEnd){uint length = bids[msg.sender].length;if (_values.length != length || _fake.length != length ||_secret.length != length)throw;uint refund;for (uint i = 0; i < length; i++){var bid = bids[msg.sender][i];var (value, fake, secret) =(_values[i], _fake[i], _secret[i]);if (bid.blindedBid != sha3(value, fake, secret))//出價未被正常揭拍,不能取回保證金。continue;refund += bid.deposit;if (!fake && bid.deposit >= value)if (placeBid(msg.sender, value))refund -= value;//保證發送者絕不可能重復取回保證金bid.blindedBid = 0;}msg.sender.send(refund);}//這是一個內部 (internal)函數,//意味著僅僅只有合約(或者從其繼承的合約)可以調用function placeBid(address bidder, uint value) internalreturns (bool success){if (value <= highestBid)return false;if (highestBidder != 0)//退還前一個最高競拍出價highestBidder.send(highestBid);highestBid = value;highestBidder = bidder;return true;}///競拍結束后發送最高出價到競拍人function auctionEnd()onlyAfter(revealEnd){if (ended) throw;AuctionEnded(highestBidder, highestBid);//發送合約擁有所有的錢,因為有一些保證金退回可能失敗了。beneficiary.send(this.balance);ended = true;}function () { throw; } } Safe Remote Purchase 安全的遠程購物contract Purchase {uint public value;address public seller;address public buyer;enum State { Created, Locked, Inactive }State public state;function Purchase(){seller = msg.sender;value = msg.value / 2;if (2 * value != msg.value) throw;}modifier require(bool _condition){if (!_condition) throw;_}modifier onlyBuyer(){if (msg.sender != buyer) throw;_}modifier onlySeller(){if (msg.sender != seller) throw;_}modifier inState(State _state){if (state != _state) throw;_}event aborted();event purchaseConfirmed();event itemReceived();///終止購物并收回以太。僅僅可以在合約未鎖定時被賣家調用。function abort()onlySellerinState(State.Created){aborted();seller.send(this.balance);state = State.Inactive;}///買家確認購買。交易包含兩倍價值的(`2 * value`)以太。///這些以太會一直鎖定到收貨確認(confirmReceived)被調用。function confirmPurchase()inState(State.Created)require(msg.value == 2 * value){purchaseConfirmed();buyer = msg.sender;state = State.Locked;}///確認你(買家)收到了貨物,這將釋放鎖定的以太。function confirmReceived()onlyBuyerinState(State.Locked){itemReceived();buyer.send(value);//我們有意忽略了返回值。seller.send(this.balance);state = State.Inactive;}function() { throw; } }后
先掛起這個吧, 這些東西需要消耗太久總結
以上是生活随笔為你收集整理的通过例子学Solidity[注释翻译]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从 Demo 中学习 Solidity
- 下一篇: 宠物商店(pet-shop) 学习笔记