Skip to content

Instantly share code, notes, and snippets.

@szerintedmi
Last active June 6, 2017 09:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save szerintedmi/ff6e60dbc411c055e59d4efa0b222bb5 to your computer and use it in GitHub Desktop.
Save szerintedmi/ff6e60dbc411c055e59d4efa0b222bb5 to your computer and use it in GitHub Desktop.
Testing gas consumption with iterable maps
pragma solidity ^0.4.8;
import "github.com/szerintedmi/solidity-itMapsLib/itMapsLib.sol";
contract GasTest {
using itMaps for itMaps.itMapUintUint;
using itMaps for itMaps.itMapUintAddress;
using itMaps for itMaps.itMapAddressUint;
using itMaps for itMaps.itMapUintBool;
using GasTestLib for GasTestLib.Game;
GasTestLib.Game game;
function addBet(uint number) returns (bool overwrittenBet) {
if (game.winningAddress != address(0)) {
// it's a first bet so clear winner from previous round
game.winningAddress = address(0);
game.smallestNumber = 0;
}
return game.im_bets.insert(msg.sender,number);
}
function updateResults() returns (uint numberOfUnrevealedOrInvalidBets) {
return game._updateResults();
}
function getResults() constant returns (address winningAddress, uint smallestNumber) {
return (game.winningAddress, game.smallestNumber);
}
}
library GasTestLib {
/* TODO: hove to structrure this? what data/logic shall we move here? */
using itMaps for itMaps.itMapAddressUint;
using itMaps for itMaps.itMapUintAddress;
using itMaps for itMaps.itMapUintBool;
struct Game {
// playeraddress => bet number , bet number is 0 until revealed
itMaps.itMapAddressUint im_bets;
// callback queryId => player address : used for retrieving playerAddress at __callback
uint smallestNumber;
address winningAddress;
ResultCalcHelper resultCalcHelper;
}
struct ResultCalcHelper {
/* temporary structure to calculate results - can't be in memory because can't create mappings and dynamic arrays in memory
could it be done without storage ?? */
itMaps.itMapUintAddress im_seenOnce; // Key:betnumber -> Value:PlayerAddress
itMaps.itMapUintBool im_seenMultiple; // Key:betnumber => Value:seen (bool)
// mapping(uint=>bool) m_seenMultiple; would be enough to calc results
// but it needs to be itmap to be able to destroy after round.
}
function _updateResults(Game storage self) internal returns (uint numberOfUnrevealedOrInvalidBets) {
// This function needs to be updated to run in batches of bets to allow
// higher number of bets evaluated without hitting the gas limit
ResultCalcHelper storage _resultCalcHelper = self.resultCalcHelper;
uint numberOfBets = self.im_bets.size() ;
uint numberToCheck;
// collect unique betnumbers in seenOnce from all bets (im_bets)
for(uint i = 0; i < numberOfBets ; i++) {
numberToCheck = self.im_bets.getValueByIndex(i); // CHECK: does it overwrite value in im_bets?
if(numberToCheck > 0) { // if this bid has been already revealed and valid...
if (_resultCalcHelper.im_seenMultiple.contains(numberToCheck) ) {
continue;
}
if (_resultCalcHelper.im_seenOnce.contains(numberToCheck)) {
_resultCalcHelper.im_seenOnce.remove(numberToCheck);
_resultCalcHelper.im_seenMultiple.insert(numberToCheck, true);
} else {
// first occurence, add to seenOnce
_resultCalcHelper.im_seenOnce.insert( numberToCheck, self.im_bets.getKeyByIndex(i));
}
} else {
numberOfUnrevealedOrInvalidBets++ ;
} // numberToCheck
} // for
// find smallestNumber in seenOnce
self.winningAddress = address(0);
self.smallestNumber = 0;
uint seenOnceCount = _resultCalcHelper.im_seenOnce.size();
for( i=0; i < seenOnceCount; i++) {
numberToCheck = _resultCalcHelper.im_seenOnce.getKeyByIndex(i);
if (numberToCheck < self.smallestNumber || self.smallestNumber == 0) {
self.smallestNumber = numberToCheck;
self.winningAddress = _resultCalcHelper.im_seenOnce.getValueByIndex(i);
}
}
// Clean up
// CHECK: is it the best way? ie. shall we just set array lengthto zero? (im_seenOnce.clear())
// https://ethereum.stackexchange.com/questions/14017/solidity-how-could-i-apply-delete-to-complete-storage-ref-with-one-call
_resultCalcHelper.im_seenOnce.destroy();
_resultCalcHelper.im_seenMultiple.destroy();
self.im_bets.destroy();
return numberOfUnrevealedOrInvalidBets;
} // updateResults
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment