[官方译文(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[注释翻译]相关推荐

  1. 官方完整HL7 ECG-XML例子及注释翻译(1)

    编者:李国帅 qq:9611153 微信lgs9611153 时间:2019-7-4 背景: 存储心电图数据的格式有很多种,比如HL7,Dicom,EDF,GDF等,其中HL7最是简单,直观,使用Xm ...

  2. IntelliJ IDEA生产力工具 -- 源码注释翻译神器

    IntelliJ IDEA生产力工具 – 源码注释翻译神器 本次给大家分享的IntelliJ IDEA提效插件是Translation. 用IDEA看源码时,难免会遇到有不认知的英文单词或翻译不通的句 ...

  3. HashMap源码注释翻译

    HashMap注释翻译 package java.util;import java.io.IOException; import java.io.InvalidObjectException; imp ...

  4. IDEA Translation(翻译插件)使用(注释翻译,单词翻译)

    1 安装Translation File->Settings->Plugins->Marketplace->输入Translation->Install. 2 注释翻译 ...

  5. Raid5.h注释翻译

    Linux内核2.6.32中的Raid5.h一上来就是150多行的注释!看起来好辛苦,简单翻译一份留在这里,翻译不对的地方希望大家指出~ 每个条纹都包含一个buffer,每个buffer和每个磁盘对应 ...

  6. 【JS 逆向百例】cnki 学术翻译 AES 加密分析

    关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途 ...

  7. 【JS 逆向百例】有道翻译接口参数逆向

    文章目录 逆向目标 逆向过程 抓包分析 参数逆向 完整代码 youdao_encrypt.js youdaofanyi.py 逆向目标 目标:有道翻译接口参数 主页:https://fanyi.you ...

  8. 通过例子学TLA+(一)-- HourClock

    前言 刚接触TLA+,将学习过程中的理解整理记录下来,用于加深理解和备忘.有对TLA+感兴趣的可以私信我,一起学习. TLA+简介 TLA+ 是一门形式规格说明语言(formal specificat ...

  9. 通过例子学TLA+(十三)--多进程与await

    多进程 之前使用的例子都是单进程的,现在用多进程来描述多个逻辑同时发生,TLA+中的多进程可以理解为其他高级语言中的多线程.为了方便理解,使用Pluscal语言来描述,TLA+ Toolbox可以将p ...

最新文章

  1. javascript迭代器_JavaScript迭代器概述
  2. 如何看待清华北大毕业生流失去国外?
  3. 源码分析shiro认证授权流程
  4. hadoop2.20+hive+sqoop+mysql数据处理案例
  5. share-jquery
  6. SAP ABAP Platform 1909最新版的 docker 镜像
  7. android蓝牙串口 hc06,Android手机通过蓝牙模块HC-06连接Arduino串口输出
  8. CVE-2021-3156:Sudo 堆缓冲区溢出漏洞(有poc,exp待更新)
  9. ViewState的原理,应用场合,注意事项
  10. Android将应用调试log信息保存在SD卡
  11. 8.11 Matching Networks 匹配网络
  12. TCP 协议(包含三次握手,四次挥手)
  13. 为资产分类定义折旧范围_SAP折旧范围
  14. Mac开发-NSTextView软回车转换为硬回车
  15. ​红旗首款奢华纯电动SUV车型上市;一起教育登陆纳斯达克;恒隆与凯悦在昆明打造君悦酒店 | 美通企业周刊...
  16. CLH lock queue的原理解释及Java实现
  17. 第十三届 蓝桥杯青少年创意编程 C++组 省赛
  18. 《AngularJS深度剖析与最佳实践》一1.1 环境准备
  19. 十大歌手Python
  20. 在xml中定义excel的sheet_XML和Excel

热门文章

  1. bigdecimal 等于0_好程序员Java培训分享BigDecimal的用法
  2. 解决webpack打包后-webkit-box-orient: vertical ;消失问题
  3. python爬虫(4)--Cookie的使用
  4. ajax中的同步异步
  5. Android-----Resources
  6. drupal6 笔记
  7. 转:两种转换mysql数据编码的方法-latin1转utf8
  8. 如果爱情不会让人受伤
  9. JAVA WEB_中间件
  10. oracle表格颜色,如何在oracle中使用光标更新特定颜色