智能合約學(xué)習(xí):近似算法WBDP(truffle + ganache-cli)

本文主要介紹了如何使用truffle + Atom進(jìn)行拍賣環(huán)節(jié)1:勝利者選擇智能合約的編寫,以及如何使用ganache-cli進(jìn)行智能合約的交互測(cè)試。


1 Trueffle框架編寫代碼

相關(guān)細(xì)節(jié)可以查看另一篇文章以太坊公開(kāi)拍賣智能合約(truffle + ganache-cli)。本文主要介紹合約實(shí)現(xiàn)瞻想,以及一些新的點(diǎn)躏鱼。

1.1 建立項(xiàng)目

PS H:\TestContract> mkdir ReverseAuction
PS H:\TestContract\ReverseAuction> cd contracts
PS H:\TestContract\ReverseAuction\contracts> truffle create contract ReverseAuction
  • \contracts:存放智能合約源代碼的地方戒良,可以看到里面已經(jīng)有一個(gè)sol文件寂玲,我們開(kāi)發(fā)的ReverseAuction.sol文件就存放在這個(gè)文件夾塔插。
  • \migrations:這是Truffle用來(lái)部署智能合約的功能,待會(huì)兒我們會(huì)新建一個(gè)類似1_initial_migration.js的文件來(lái)部署ReverseAuction.sol拓哟。
  • \test:測(cè)試智能合約的代碼放在這里想许,支持jssol測(cè)試。
  • truffle-config.jstruffle.jsTruffle的配置文件,需要配置要連接的以太坊網(wǎng)絡(luò)断序。

1.2 創(chuàng)建合約

需求:
請(qǐng)實(shí)現(xiàn)一個(gè)拍賣協(xié)議流纹,在該協(xié)議中,每個(gè)用戶可以提交自己的出價(jià)违诗。
根據(jù)邊際成本排序漱凝,每次選擇邊際成本最低的報(bào)價(jià),直到所有的任務(wù)被包含较雕。

詳細(xì)算法可以看參考文獻(xiàn)[1]碉哑,算法有什么不對(duì)的請(qǐng)輕拍,我現(xiàn)在只是測(cè)試一下能不能用智能合約寫出一個(gè)簡(jiǎn)單的拍賣亮蒋。

pragma solidity ^0.4.22;

contract ReverseAuction {
  struct Bid{
      address id;  // identity of employee
      uint k;   // k-th bid of user i
  //    bool selected;  // whether it is selected
      uint[] Q; // a subset of sensing tasks that employees are willing to sense
      uint bid;  //  corresponding bid
      uint increaseR;
  }

  uint[] public tasks;   // published tasks
  address public provider;  // task provider
  uint public amount; // amount of tasks

  //mapping (address => Bid[]) public bids;   // mapping from address to bid
  Bid[] public bids;
//  mapping (address => Bid[]) public selected_bids;  // winning bids
  Bid[] public selected_bids;
  uint public selected_bids_num;

  Bid[] public backup_bids;

  uint[] public currentQ;  // tasks set currently included in the selected bids

  uint public utility;  // social welfare

  event AuctionEnded(uint utility); // auction end event

  event LogBid(address, uint, uint[], uint, uint);
  function log(address id, uint k, uint[] Q, uint bid, uint r) internal {
    emit LogBid(id, k, Q, bid, r);
  }

  constructor(address _provider) {
      provider = _provider;
      amount = 0;
      selected_bids_num = 0;
      utility = 0;
  }

  function setTasks(uint _amount, uint[] _tasks) public {
      amount = _amount;
      tasks = new uint[](_amount);
      for (uint i = 0; i < amount; i++){
          tasks[i] = _tasks[i];
      }
  }

  function getTasks() constant public returns(uint[]){
      return tasks;
  }

  function addBid(uint _k, uint[] _Q, uint _bid) public {
      require(_Q.length > 0 && _bid > 0);
      bids.push(Bid({id: msg.sender, k: _k, Q: _Q, bid: _bid, increaseR: 0}));
  }

  function getAllBidsNum() constant public returns (uint) {
      return bids.length;
  }

  function getAllBids(uint index) constant public returns(address, uint, uint[], uint, uint) {
      return (bids[index].id, bids[index].k, bids[index].Q, bids[index].bid, bids[index].increaseR);
  }

  function getBackupBids(uint index) constant public returns(address, uint, uint[], uint, uint) {
      return (backup_bids[index].id, backup_bids[index].k, backup_bids[index].Q, backup_bids[index].bid, backup_bids[index].increaseR);
  }

  function getSocialWelfare() constant public returns (uint) {
      return utility;
  }

  function getSelectedBidsNum() constant public returns(uint) {
      return selected_bids.length;
  }

  function getSelectedBids(uint index) constant public returns(address, uint, uint[], uint, uint) {
     return (selected_bids[index].id, selected_bids[index].k, selected_bids[index].Q, selected_bids[index].bid, selected_bids[index].increaseR);
  }

  function getCurrentQNum() constant public returns (uint) {
      return currentQ.length;
  }

  function selectWinners() public returns (uint[]) {
      require(bids.length != 0 && currentQ.length != amount);
      backupAllBids();
      while (currentQ.length != amount) {
          // compute r(bid) for each bid
          computeIncreaseR(bids, currentQ);

          // sort increaseR in nondecreasing order
          //  and return the top bid
          sortBidByIncreaseR(bids, int(0), int(bids.length-1));

          // increasing order
          Bid memory bid = Bid({id: bids[0].id, k: bids[0].k, Q: bids[0].Q, bid:bids[0].bid, increaseR: bids[0].increaseR});

          selected_bids.push(bid);
          utility += bid.bid;

          // find union of currentQ and bid.Q, then put into the currentQ
          setUnion(currentQ, bid.Q);

          // remove the selected bid from B
          removeBid(0, bids);

          // delete bids that conflict with the selected bid
          deleteConflictBids(bid);

      }
      return currentQ;
  }

  // print all bid
  function printAllBids() public {
      require(bids.length > 0);
      for (uint i = 0; i < bids.length; i++) {
        emit LogBid(bids[i].id, bids[i].k, bids[i].Q, bids[i].bid, bids[i].increaseR);
      }
  }

  function testCopy(uint[] _Q) public returns (address, uint, uint[], uint, uint){
      bid1 = Bid({id: msg.sender, k: 0, Q:_Q, bid: 6, increaseR:0});
      bid2 = bid1;
    //  copyBid(bid2, bid1);
      return (bid2.id, bid2.k, bid2.Q, bid2.bid, bid2.increaseR);
  }

  // backup the original bids
  function backupAllBids() internal {
      uint length = bids.length;
    //  backup_bids = new Bid[](length);
      delete backup_bids;
      for (uint i = 0; i < length; i++) {
          backup_bids.push(bids[i]);
      }
  }

  // compute r(bid) for each bid
  function computeIncreaseR(Bid[] storage _bids, uint[] _currentQ) internal {
    for (uint i = 0; i < _bids.length; i++) {
        uint diffNum = isSubsetOfcurrentQ(_bids[i].Q, _currentQ); // |Q-currentQ|
        // Q is subset of currentQ, delete the bid contains Q
        if (diffNum == 0) {
            removeBid(i, _bids);
            i--;
            continue;
        }
        _bids[i].increaseR = _bids[i].bid / diffNum;
    }
  }

  // if Q is the subset of currentQ, delete Q
  // otherwise, compute the marginal benefit of Q
  function isSubsetOfcurrentQ(uint[] _Q, uint[] _currentQ) internal returns (uint){
      uint count = _Q.length;
      for (uint  i = 0; i < _Q.length; i++) {
          for (uint j = 0; j < _currentQ.length; j++) {
              if(_Q[i] == _currentQ[j]) {
                  count--;
                  break;  // jump out of the loop as soon as you find the same one
              }
          }
      }
      return count;
  }

  // delete the bid at the specified location
  function removeBid(uint index, Bid[] storage _bids) internal {
      uint length = _bids.length;
      if (index < 0 || index > length) return;
      for (uint i = index; i < length - 1; i++) {
          _bids[i] = _bids[i+1];
          /*
          _bids[i].id = _bids[i+1].id;
          _bids[i].k = _bids[i+1].k;
          _bids[i].Q = _bids[i+1].Q;
          _bids[i].bid = _bids[i+1].bid;
          _bids[i].increaseR = _bids[i+1].increaseR;
          */
      }
      delete _bids[length - 1];
      _bids.length--;
  }

  function sortBidByIncreaseR(Bid[] storage R, int i, int j) internal {
      if (R.length == 0) return;
      quickSort(R, i, j);
  }

  function quickSort(Bid[] storage R, int i, int j) internal {
      if (i < j) {
          int pivot = partition(R, i, j);
          quickSort(R, i, pivot - 1);
          quickSort(R, pivot + 1, j);
      }
  }

  function partition(Bid[] storage R, int i, int j) internal returns(int){
    //  Bid temp = R[i];
      Bid memory temp = Bid({id: R[uint(i)].id, k: R[uint(i)].k, Q: R[uint(i)].Q, bid:R[uint(i)].bid, increaseR: R[uint(i)].increaseR});
    //  copyBid(temp, R[i]);
      while (i < j) {
          while (i < j && R[uint(j)].increaseR >= temp.increaseR)
              j--;
          if (i < j) {
              R[uint(i)] = R[uint(j)];
              i++;
          }
          while (i < j && R[uint(i)].increaseR <= temp.increaseR)
              i++;
          if (i < j) {
              R[uint(j)] = R[uint(i)];
              j--;
          }
      }
    //  copyBid(R[i] , temp);
      R[uint(i)] = Bid({id: temp.id, k: temp.k, Q: temp.Q, bid: temp.bid, increaseR: temp.increaseR});
      delete temp;
      return i;
  }

  // find the union of two sets
  function setUnion(uint[] storage v1, uint[] v2) internal {
      for (uint i = 0; i < v2.length; i++) {
          if (isElementInSet(v1, v2[i]))  continue;
          v1.push(v2[i]);
      }
  }

  // check whether element is in set v
  function isElementInSet(uint[] v, uint element) internal returns(bool){
      for (uint i = 0; i < v.length; i++) {
          if (v[i] == element) return true;
      }
      return false;
  }

  // delete conflict bids conflict with the bid
  function deleteConflictBids(Bid bid) internal {
      uint length = bid.Q.length;
      int i = 0;
      while (uint(i) < bids.length) {
        //  Bid temp = bids[i];
          Bid memory temp = Bid({id: bids[uint(i)].id, k: bids[uint(i)].k, Q: bids[uint(i)].Q, bid:bids[uint(i)].bid, increaseR: bids[uint(i)].increaseR});
          //copyBid(temp, bids[i]);
          i++;
          // no conflict
          if (temp.Q.length != length) continue;
          // may have conflict
          uint flag = isConflictBid(temp, bid);
          if (flag == 0) {
              --i;
              removeBid(uint(i), bids);
          }
      }
  //    delete temp;
  }

  // check if this two bids conflict
  function isConflictBid(Bid bid, Bid baseBid) internal returns(uint) {
      uint length  = baseBid.Q.length;
      uint flag = length;
      for (uint i = 0; i < length; i++) {
          for (uint j = 0; j < length; j++) {
              if (bid.Q[i] == baseBid.Q[j]) {
                  flag--;
                  break;
              }
          }
      }
      return flag;
  }

}

常見(jiàn)錯(cuò)誤

  1. ufixeduint
    最開(kāi)始扣典,我是定義ufixed increaseR; 雖然Solidity從0.4.20開(kāi)始支持浮點(diǎn)數(shù),然而這些編譯器并不支持慎玖,會(huì)報(bào)錯(cuò)UnimplementedFeatureError: Not yet implemented - FixedPointType.贮尖。所以只好改成了uint無(wú)符號(hào)整型。即使會(huì)影響精度趁怔,但這也是沒(méi)有辦法的事湿硝,只能等待EVM的更新了。

  2. memorystorage
    變量類型润努,可以在網(wǎng)上找到一些關(guān)于他們的介紹关斜,如:Solidity的數(shù)據(jù)位置特性深入詳解。簡(jiǎn)單的理解铺浇,智能合約中的狀態(tài)變量痢畜,也可以說(shuō)是全局變量吧,都是storage的鳍侣,而函數(shù)中聲明的大多數(shù)變量都是memory類型的丁稀。

    看源代碼function backupAllBids() {}函數(shù)中被注釋掉的一句話backup_bids = new Bid[] (length);

    最開(kāi)始我寫了一個(gè)函數(shù),函數(shù)中會(huì)調(diào)用很多子函數(shù)倚聚,通過(guò)truffle編譯后线衫,只會(huì)報(bào)出UnimplementedFeatureError: Copying of type struct ReverseAuction.Bid memory[] memory to storage not yet supported.錯(cuò)誤。

    backup_bidsstorage類型的惑折,這里的new Bid[] (length)卻是memory的授账。不過(guò)我這里有一個(gè)疑惑是枯跑,在function setTasks() {}函數(shù)中,我同樣使用了tasks = new uint[] (_amount);矗积,這句話卻是正確的全肮,我也不理解是為什么〖罚可能是因?yàn)?code>Bid是我自定義的比較復(fù)雜的結(jié)構(gòu)體吧。不過(guò)不需要自己分配空間休建,智能合約也依然可以使用乍恐,所以目前比較好的方法就是直接刪掉這句話。

    EVM無(wú)法進(jìn)行debug测砂, 我也嘗試了利用event事件函數(shù)來(lái)打印log茵烈,不過(guò)沒(méi)有成功,所以很難找出錯(cuò)誤在哪兒砌些。只好一個(gè)個(gè)寫測(cè)試函數(shù)呜投,在cmd中不斷重新構(gòu)造對(duì)象,進(jìn)行單元測(cè)試存璃。雖然這一次能找到仑荐,但是下一次依然很麻煩,希望趕緊出一個(gè)簡(jiǎn)單方便的以太坊調(diào)試工具纵东。

  3. uintint
    在我將上面的問(wèn)題都解決后粘招,我還是決定先把所有調(diào)用的子函數(shù)都測(cè)試完再將它們整合起來(lái),這時(shí)候偎球,function deleteConflictBids() {} 函數(shù)就報(bào)錯(cuò)了洒扎,EVM的特性,不會(huì)告訴你錯(cuò)在哪兒的衰絮,??袍冷,只給出一句話Error: VM Exception while processing transaction: invalid opcode,就只能自己找了猫牡。

    我大概記得之前曾經(jīng)看到過(guò)智能合約中進(jìn)行排序或者類似i--這種類型的語(yǔ)句胡诗,很有可能會(huì)越界,因?yàn)槎x的是uint 類型的雖然我們并不會(huì)用到i = -1這種镊掖,但是當(dāng)i == 0時(shí)乃戈,有時(shí)候還會(huì)進(jìn)行一次i--操作才會(huì)跳出函數(shù),因此這種情況下會(huì)報(bào)錯(cuò)亩进。

    然而在智能合約中症虑,所有的數(shù)組取值操作,下標(biāo)data[i]這里的i必須是uint類型的归薛,不然會(huì)報(bào)錯(cuò)谍憔。所以就需要自己多次進(jìn)行類型轉(zhuǎn)換匪蝙。如:定義int i; 使用時(shí)bids[uint(i)]

    如上方的源代碼那樣修改之后习贫,函數(shù)調(diào)用成功逛球。

  4. 單元測(cè)試 & 集成測(cè)試
    我發(fā)現(xiàn)單獨(dú)測(cè)試將winner加入selected_bids,以及將selected_bids_num++這幾句代碼仿佛直接被編譯器跳過(guò)了苫昌,無(wú)論重新編譯幾次颤绕,也不會(huì)執(zhí)行。這也導(dǎo)致了后面函數(shù)的調(diào)用失敗祟身。

    我想可能是編譯器自己的原因奥务,就直接將函數(shù)整合了,重新編譯袜硫,進(jìn)行整體的集成測(cè)試氯葬,然后函數(shù)完全運(yùn)行成功。

    所以有網(wǎng)友說(shuō)直接用自帶remix編譯成abi婉陷,然后自己部署帚称,不要用類似truffle之類的工具,畢竟也是其他開(kāi)發(fā)者自己編寫的秽澳,會(huì)有很多bug闯睹。remix會(huì)實(shí)時(shí)編譯,也挺方便肝集。但是使用框架畢竟要容易一點(diǎn)瞻坝,目前還能忍受一些小小的錯(cuò)誤。

    如何用remix編譯部署的方法杏瞻,我另一篇文章也有簡(jiǎn)單介紹Windows搭建私有鏈所刀,創(chuàng)建部署Hello world智能合約,自己可以自由組合用什么工具寫編譯智能合約(atom+truffle, remix, wallet...) 捞挥,再用什么方法部署智能合約(truffle, 自己創(chuàng)建的私有鏈浮创,wallet...)。網(wǎng)上的方法也挺多的砌函。

1.3 編譯合約

同樣可以參考之前的文章斩披,有詳細(xì)說(shuō)明。
在項(xiàng)目根目錄ReverseAuction的powershell中執(zhí)行truffle compile命令:

PS H:\TestContract\ReverseAuction> truffle compile
Compiling .\contracts\Migrations.sol...
Compiling .\contracts\ReverseAuction.sol...

Compilation warnings encountered:

....

Writing artifacts to .\build\contracts

2 Ganache-cli 部署測(cè)試智能合約

2.1 啟動(dòng)ganache-cli

打開(kāi)powershell終端讹俊,可以看到ganache-cli啟動(dòng)后自動(dòng)建立了10個(gè)賬號(hào)(Accounts)垦沉,與每個(gè)賬號(hào)對(duì)應(yīng)的私鑰(Private Key)。每個(gè)賬號(hào)中都有100個(gè)測(cè)試用的以太幣(Ether)仍劈。
Note. ganache-cli僅運(yùn)行在內(nèi)存中厕倍,因此每次重開(kāi)時(shí)都會(huì)回到全新的狀態(tài)。

C:\Users\aby>ganache-cli

2.2 部署合約

(1)migrations目錄下創(chuàng)建一個(gè)名字叫做2_deploy_contracts.js的文件贩疙。文件中的內(nèi)容為:

var ReverseAuction = artifacts.require('./ReverseAuction');

module.exports = function(deployer){
    deployer.deploy(ReverseAuction, '0x540dcc00853f82dcba9d5871e1013d55d3bd9461')
}

(2)修改truffle.js文件讹弯,連接本地ganache-cli環(huán)境况既。參數(shù)在最開(kāi)初始化ganache-cli環(huán)境的窗口可以看到。

module.exports = {
  // See <http://truffleframework.com/docs/advanced/configuration>
  // to customize your Truffle configuration!
  networks: {
        development: {
            host: '127.0.0.1',
            port: 8545,
            network_id: "*" // match any network id
        }
    }
};

(3)現(xiàn)在執(zhí)行truffle migrate命令组民,我們可以將ReverseAuction.sol原始碼編譯成Ethereum bytecode棒仍。

PS H:\TestContract\ReverseAuction> truffle migrate --reset
Using network 'development'.

Running migration: 1_initial_migration.js
  Deploying Migrations...
  ... 
Saving artifacts...

2.3 與合約交互

truffle提供命令行工具,執(zhí)行truffle console命令后臭胜,可用Javascript來(lái)和剛剛部署的合約互動(dòng)莫其。

PS H:\TestContract\SimpleAuction> truffle console
truffle(development)>

2.3.1 參與拍賣的賬戶

我們需要準(zhǔn)備一些測(cè)試賬戶。
它會(huì)把第一個(gè)帳戶的地址分配給變量account0耸三,第二個(gè)帳戶分配給變量account1榜配。Web3是一個(gè)JavaScript API,它將RPC調(diào)用包裝起來(lái)以方便我們與區(qū)塊鏈進(jìn)行交互吕晌。
我在這里將第9個(gè)賬戶作為部署合約初始化的拍賣發(fā)起人。
其余5個(gè)賬戶會(huì)進(jìn)行報(bào)價(jià)临燃。

PS H:\TestContract\ReverseAuction> truffle console
truffle(development)> address = web3.eth.accounts[9];
'0x540dcc00853f82dcba9d5871e1013d55d3bd9461'
truffle(development)> a1 = web3.eth.accounts[1];
'0x68e8a5c2041d181b83b45e6d43bd6632c2fbd4c1'
truffle(development)> a2 = web3.eth.accounts[2];
'0x05f5daeb06b8c9d4e158b9fa0ce3c36805a2542a'
truffle(development)> a3 = web3.eth.accounts[3];
'0x1e78baa740a7241fc92f5d47ae13d6a5f304b516'
truffle(development)> a4 = web3.eth.accounts[4];
'0x489fbcee812f313596ed7fdc816b588383b9c3f7'
truffle(development)> a5 = web3.eth.accounts[5];
'0x6125b3b7e1bf338696eae491df24710ae13258eb'

2.3.2 啟動(dòng)拍賣

現(xiàn)在我們需要先啟動(dòng)一個(gè)拍賣,才能進(jìn)行接下來(lái)的操作。

truffle(development)> let contract
undefined
truffle(development)>  ReverseAuction.deployed().then(instance => contract = instance);

任務(wù)提供者設(shè)置任務(wù)我抠。

truffle(development)> tasks = [1,2,3,4,5,6];
[ 1, 2, 3, 4, 5, 6 ]
truffle(development)> contract.setTasks(6,tasks,{from:address});

truffle(development)> contract.getTasks.call();
[ BigNumber { s: 1, e: 0, c: [ 1 ] },
  BigNumber { s: 1, e: 0, c: [ 2 ] },
  BigNumber { s: 1, e: 0, c: [ 3 ] },
  BigNumber { s: 1, e: 0, c: [ 4 ] },
  BigNumber { s: 1, e: 0, c: [ 5 ] },
  BigNumber { s: 1, e: 0, c: [ 6 ] } ]

2.3.3 開(kāi)始報(bào)價(jià)

此時(shí)我們用5個(gè)賬號(hào)分別調(diào)用addBid()進(jìn)行報(bào)價(jià)冲粤。

truffle(development)> contract.addBid(0,[1,3,4],12,{from:a1});
truffle(development)> contract.addBid(0,[1,5],6,{from:a2});
truffle(development)> contract.addBid(0,[2,3,4],15,{from:a3});
truffle(development)> contract.addBid(0,[3,4,5,6],16,{from:a4});
truffle(development)> contract.addBid(0,[2,4,6],9,{from:a5});

并且查看此時(shí)a1報(bào)價(jià)(注釋是我寫文章的時(shí)候加的,為了方便查看爪瓜,命令行中并沒(méi)有)蹬跃。

truffle(development)> contract.getAllBids.call(0)
[ '0x68e8a5c2041d181b83b45e6d43bd6632c2fbd4c1',   // id
  BigNumber { s: 1, e: 0, c: [ 0 ] },             // k
  [ BigNumber { s: 1, e: 0, c: [Array] },         // Q
    BigNumber { s: 1, e: 0, c: [Array] },
    BigNumber { s: 1, e: 0, c: [Array] } ],
  BigNumber { s: 1, e: 1, c: [ 12 ] },            // bid
  BigNumber { s: 1, e: 0, c: [ 0 ] } ]            // increaseR

2.3.4 啟動(dòng)winner selection算法

調(diào)用function selectWinners() {}函數(shù)進(jìn)行winner selection。

truffle(development)> contract.selectWinners({from:address})
{ tx: '0x376316e4346743675be052b07323b5ebac115d92a80e9cf0571203d5f0207b72',
  receipt:
   { transactionHash: '0x376316e4346743675be052b07323b5ebac115d92a80e9cf0571203d5f0207b72',
     transactionIndex: 0,
     blockHash: '0x8e71731c25b51e8561483cbdeabaaaf8f7eefe7a3a9496f5990bc65043b951c3',
     blockNumber: 11,
     gasUsed: 2515856,
     cumulativeGasUsed: 2515856,
     contractAddress: null,
     logs: [],
     status: '0x1',
     logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' },
  logs: [] }

然后查看當(dāng)前原始Bidsbids中沒(méi)被選中的報(bào)價(jià)數(shù)铆铆。

truffle(development)> contract.getAllBidsNum.call()
BigNumber { s: 1, e: 0, c: [ 2 ] }

再看看selected_bids中被選中的報(bào)價(jià)數(shù)蝶缀。

truffle(development)> contract.getSelectedBidsNum.call()
BigNumber { s: 1, e: 0, c: [ 3 ] }

最后分別查看selected_bids中每個(gè)被選中報(bào)價(jià)的詳情。

truffle(development)> contract.getSelectedBids.call(0)
[ '0x6125b3b7e1bf338696eae491df24710ae13258eb',
  BigNumber { s: 1, e: 0, c: [ 0 ] },
  [ BigNumber { s: 1, e: 0, c: [Array] },
    BigNumber { s: 1, e: 0, c: [Array] },
    BigNumber { s: 1, e: 0, c: [Array] } ],
  BigNumber { s: 1, e: 0, c: [ 9 ] },
  BigNumber { s: 1, e: 0, c: [ 3 ] } ]
truffle(development)> contract.getSelectedBids.call(1)
[ '0x05f5daeb06b8c9d4e158b9fa0ce3c36805a2542a',
  BigNumber { s: 1, e: 0, c: [ 0 ] },
  [ BigNumber { s: 1, e: 0, c: [Array] },
    BigNumber { s: 1, e: 0, c: [Array] } ],
  BigNumber { s: 1, e: 0, c: [ 6 ] },
  BigNumber { s: 1, e: 0, c: [ 3 ] } ]
truffle(development)> contract.getSelectedBids.call(2)
[ '0x68e8a5c2041d181b83b45e6d43bd6632c2fbd4c1',
  BigNumber { s: 1, e: 0, c: [ 0 ] },
  [ BigNumber { s: 1, e: 0, c: [Array] },
    BigNumber { s: 1, e: 0, c: [Array] },
    BigNumber { s: 1, e: 0, c: [Array] } ],
  BigNumber { s: 1, e: 1, c: [ 12 ] },
  BigNumber { s: 1, e: 1, c: [ 12 ] } ]

最后看一看是否已經(jīng)覆蓋了全部的任務(wù)薄货,同時(shí)打印social welfare翁都。

truffle(development)> contract.getCurrentQNum.call()
BigNumber { s: 1, e: 0, c: [ 6 ] }
truffle(development)> contract.getSocialWelfare.call()
BigNumber { s: 1, e: 1, c: [ 27 ] }

可以看出所有任務(wù)都被覆蓋到。

結(jié)果與我用c++跑出來(lái)的結(jié)果一樣谅猾。

下一篇文章柄慰,將會(huì)用智能合約實(shí)現(xiàn)參考文獻(xiàn)[1]的第二部分critical payment算法。

本文作者:Joyce
文章來(lái)源:http://www.reibang.com/p/8bd49c1d5c39
版權(quán)聲明:轉(zhuǎn)載請(qǐng)注明出處税娜!

2018年7月26日


Reference


  1. TRAC: Truthful Auction for Location-Aware Collaborative Sensing in Mobile Crowdsourcing ? ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末坐搔,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子敬矩,更是在濱河造成了極大的恐慌概行,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谤绳,死亡現(xiàn)場(chǎng)離奇詭異占锯,居然都是意外死亡袒哥,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門消略,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)堡称,“玉大人,你說(shuō)我怎么就攤上這事艺演∪唇簦” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵胎撤,是天一觀的道長(zhǎng)晓殊。 經(jīng)常有香客問(wèn)我,道長(zhǎng)伤提,這世上最難降的妖魔是什么巫俺? 我笑而不...
    開(kāi)封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮肿男,結(jié)果婚禮上介汹,老公的妹妹穿的比我還像新娘。我一直安慰自己舶沛,他們只是感情好嘹承,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著如庭,像睡著了一般叹卷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上坪它,一...
    開(kāi)封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天骤竹,我揣著相機(jī)與錄音,去河邊找鬼哟楷。 笑死瘤载,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的卖擅。 我是一名探鬼主播鸣奔,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼惩阶!你這毒婦竟也來(lái)了挎狸?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤断楷,失蹤者是張志新(化名)和其女友劉穎锨匆,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡恐锣,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年茅主,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片土榴。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡诀姚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出玷禽,到底是詐尸還是另有隱情赫段,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布矢赁,位于F島的核電站糯笙,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏撩银。R本人自食惡果不足惜给涕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望额获。 院中可真熱鬧稠炬,春花似錦、人聲如沸咪啡。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)撤摸。三九已至,卻和暖如春褒纲,著一層夾襖步出監(jiān)牢的瞬間准夷,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工莺掠, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留衫嵌,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓彻秆,卻偏偏與公主長(zhǎng)得像楔绞,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子唇兑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345