From 26c67a59f1cdb9b36cbb3a503500ee8622e9e06e Mon Sep 17 00:00:00 2001 From: kagel Date: Tue, 6 Sep 2016 13:30:05 +0300 Subject: [PATCH] No need to compile contract each time --- resources/contracts/wallet.data | 1 + resources/sol/wallet.sol | 386 -------------------------------- src/clj/commiteth/eth/core.clj | 26 +-- 3 files changed, 12 insertions(+), 401 deletions(-) create mode 100644 resources/contracts/wallet.data delete mode 100644 resources/sol/wallet.sol diff --git a/resources/contracts/wallet.data b/resources/contracts/wallet.data new file mode 100644 index 0000000..f8664a4 --- /dev/null +++ b/resources/contracts/wallet.data @@ -0,0 +1 @@ +0x6060604052604051611166380380611166833981016040908152815160805160a0519190930180516001908101815533600160a060020a0316600381905560009081526101026020529384205592918190849084905b825181101560cc578281815181101560025760209081029091010151600160a060020a0316600282810161010081101560025701558251600282019061010290600090869085908110156002576020908102909101810151600160a060020a03168252810191909152604001600020556001016055565b50600055506101058190556201518042046101075550505050611073806100f36000396000f3606060405236156100da5760e060020a6000350463173825d9811461012c5780632f54bf6e146101805780634123cb6b146101a857806352375093146101b15780635c52c2f5146101bb578063659010e7146101e55780637065cb48146101ef578063746c91711461021c578063797af62714610225578063b20d30a914610238578063b61d27f614610265578063b75c7dc614610286578063ba51a6df146102b5578063c2cf7326146102e2578063c41a360a14610320578063cbf0b0c014610345578063f00d4b5d14610372578063f1736d86146103a4575b6103ae600034111561012a5760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b6103ae60043560006000366040518083838082843782019150509250505060405180910390206103f3815b600160a060020a03331660009081526101026020526040812054818082811415610ce757610e51565b6103b06004355b600160a060020a03811660009081526101026020526040812054115b919050565b6103c460015481565b6103c46101075481565b6103ae60003660405180838380828437820191505092505050604051809103902061057281610157565b6103c46101065481565b6103ae60043560003660405180838380828437820191505092505050604051809103902061058181610157565b6103c460005481565b6103b06004355b60008161064781610157565b6103ae60043560003660405180838380828437820191505092505050604051809103902061089681610157565b6103c46004803590602480359160443591820191013560006108a233610187565b6103ae600435600160a060020a03331660009081526101026020526040812054908082811415610b0f57610b8e565b6103ae600435600036604051808383808284378201915050925050506040518091039020610b9481610157565b6103b0600435602435600082815261010360209081526040808320600160a060020a03851684526101029092528220548281811415610bec57610c01565b6103d660043560006002600183016101008110156100025750505060038101546101a3565b6103ae600435600036604051808383808284378201915050925050506040518091039020610c0a81610157565b6103ae6004356024356000600036604051808383808284378201915050925050506040518091039020610c1b81610157565b6103c46101055481565b005b604080519115158252519081900360200190f35b60408051918252519081900360200190f35b60408051600160a060020a03929092168252519081900360200190f35b1561045d57600160a060020a0383166000908152610102602052604081205492508214156104625761045d565b60408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a15b505050565b600160016000505403600060005054111561047c5761045d565b600060028361010081101561000257508301819055600160a060020a038416815261010260205260408120556105335b6101045460005b81811015610e59576101048054610108916000918490811015610002576000918252602080832090910154835282019290925260400181208054600160a060020a0319168155600181810183905560028281018054858255939493909281161561010002600019011604601f819010610ed157505b5050506001016104b3565b6104205b60015b60015481101561057e575b600154811080156105655750600281610100811015610002570154600014155b15610eef57600101610545565b1561057e576000610106555b50565b1561060e5761061282610187565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005055600154600160a060020a03831660008181526101026020908152604091829020939093558051918252517f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3929181900390910190a15b5050565b1561061c5761060e565b6106246104ac565b60015460fa901061063757610637610537565b60015460fa901061058f5761060e565b156107595760008381526101086020526040812054600160a060020a03161461075957604060008190208054600182810154935160029384018054600160a060020a0394909416959490939192839285929181161561010002600019011604801561078a5780601f1061075f5761010080835404028352916020019161078a565b820191906000526020600020905b8154815290600101906020018083116106d657829003601f168201915b5050965050505050505060405180910390a16000838152610108602052604081208054600160a060020a0319168155600181810183905560028281018054858255939493909281161561010002600019011604601f81901061086457505b505050600191505b50919050565b820191906000526020600020905b81548152906001019060200180831161076d57829003601f168201915b505091505060006040518083038185876185025a03f1505050600084815261010860209081526040805192819020805460018281015433600160a060020a0381811689529688018c9052948701819052919094166060860181905260a06080870181815260029485018054978816156101000260001901909716949094049087018190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a975093958a9592949193909160c0830190849080156106f35780601f106106c8576101008083540402835291602001916106f3565b601f01602090049060005260206000209081019061075191905b80821115610892576000815560010161087e565b5090565b1561060e575061010555565b15610ad7576108b6846000610fcc33610187565b15610975577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843782019150509250505060006040518083038185876185025a03f15060009350610ad792505050565b6000364360405180848480828437820191505082815260200193505050506040518091039020905080506109a88161022c565b1580156109cb575060008181526101086020526040812054600160a060020a0316145b15610ad75760008181526101086020908152604082208054600160a060020a0319168817815560018181018890556002918201805481865294849020909491821615610100026000190190911691909104601f908101929092048101918591908790839010610adf5760ff198135168380011785555b50610a4d92915061087e565b50507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32813386888787604051808760001916815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b82800160010185558215610a41579182015b82811115610a41578235826000505591602001919060010190610af1565b50506000828152610103602052604081206001810154600284900a929083161115610b8e5780546001828101805492909101835590839003905560408051600160a060020a03331681526020810186905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b50505050565b1561060e57600154821115610ba85761060e565b6000829055610bb56104ac565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001820154600282900a9081166000141593505b50505092915050565b1561060e5781600160a060020a0316ff5b15610b8e57610c2983610187565b15610c3357610b8e565b600160a060020a038416600090815261010260205260408120549250821415610c5b57610b8e565b610c636104ac565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a150505050565b60008581526101036020526040812080549093501415610d81576000805483556001838101919091556101048054918201808255828015829011610d3e57818360005260206000209182019101610d3e919061087e565b505050600283018190556101048054879290811015610002576000919091527f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe01555b506001810154600283900a90811660001415610e515760408051600160a060020a03331681526020810187905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1815460019011610e3e57600085815261010360205261010480546040909220600201549091811015610002576040600090812092815260208082209092018190558781526101039091528082556001828101829055600292909201559350610e51565b8154600019018255600182018054821790555b505050919050565b61060e6101045460005b81811015611037576101048054829081101561000257600091825260208220015414610ec9576101048054610103916000918490811015610002576020600081812093815292909101548352820192909252604001812081815560018101829055600201555b600101610e63565b601f016020900490600052602060002090810190610528919061087e565b5b60018054118015610f1257506001546002906101008110156100025701546000145b15610f265760018054600019019055610ef0565b60015481108015610f495750600154600290610100811015610002570154600014155b8015610f6357506002816101008110156100025701546000145b15610fc757600154600290610100811015610002570154600282610100811015610002570155806101026000600283610100811015610002570154815260208101919091526040016000908120919091556001546002906101008110156100025701555b61053a565b156101a35761010754610fe25b62015180420490565b1115610ffb57600061010655610ff6610fd9565b610107555b61010654808301108015906110195750610106546101055490830111155b1561102f575061010680548201905560016101a3565b5060006101a3565b610104805460008083559190915261045d907f4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe9081019061087e56 diff --git a/resources/sol/wallet.sol b/resources/sol/wallet.sol deleted file mode 100644 index dc69cd6..0000000 --- a/resources/sol/wallet.sol +++ /dev/null @@ -1,386 +0,0 @@ -//sol Wallet -// Multi-sig, daily-limited account proxy/wallet. -// @authors: -// Gav Wood -// inheritable "property" contract that enables methods to be protected by requiring the acquiescence of either a -// single, or, crucially, each of a number of, designated owners. -// usage: -// use modifiers onlyowner (just own owned) or onlymanyowners(hash), whereby the same hash must be provided by -// some number (specified in constructor) of the set of owners (specified in the constructor, modifiable) before the -// interior is executed. -contract multiowned { - - // TYPES - - // struct for the status of a pending operation. - struct PendingState { - uint yetNeeded; - uint ownersDone; - uint index; - } - - // EVENTS - - // this contract only has six types of events: it can accept a confirmation, in which case - // we record owner and operation (hash) alongside it. - event Confirmation(address owner, bytes32 operation); - event Revoke(address owner, bytes32 operation); - // some others are in the case of an owner changing. - event OwnerChanged(address oldOwner, address newOwner); - event OwnerAdded(address newOwner); - event OwnerRemoved(address oldOwner); - // the last one is emitted if the required signatures change - event RequirementChanged(uint newRequirement); - - // MODIFIERS - - // simple single-sig function modifier. - modifier onlyowner { - if (isOwner(msg.sender)) - _ - } - // multi-sig function modifier: the operation must have an intrinsic hash in order - // that later attempts can be realised as the same underlying operation and - // thus count as confirmations. - modifier onlymanyowners(bytes32 _operation) { - if (confirmAndCheck(_operation)) - _ - } - - // METHODS - - // constructor is given number of sigs required to do protected "onlymanyowners" transactions - // as well as the selection of addresses capable of confirming them. - function multiowned(address[] _owners, uint _required) { - m_numOwners = _owners.length + 1; - m_owners[1] = uint(msg.sender); - m_ownerIndex[uint(msg.sender)] = 1; - for (uint i = 0; i < _owners.length; ++i) - { - m_owners[2 + i] = uint(_owners[i]); - m_ownerIndex[uint(_owners[i])] = 2 + i; - } - m_required = _required; - } - - // Revokes a prior confirmation of the given operation - function revoke(bytes32 _operation) external { - uint ownerIndex = m_ownerIndex[uint(msg.sender)]; - // make sure they're an owner - if (ownerIndex == 0) return; - uint ownerIndexBit = 2**ownerIndex; - var pending = m_pending[_operation]; - if (pending.ownersDone & ownerIndexBit > 0) { - pending.yetNeeded++; - pending.ownersDone -= ownerIndexBit; - Revoke(msg.sender, _operation); - } - } - - // Replaces an owner `_from` with another `_to`. - function changeOwner(address _from, address _to) onlymanyowners(sha3(msg.data)) external { - if (isOwner(_to)) return; - uint ownerIndex = m_ownerIndex[uint(_from)]; - if (ownerIndex == 0) return; - - clearPending(); - m_owners[ownerIndex] = uint(_to); - m_ownerIndex[uint(_from)] = 0; - m_ownerIndex[uint(_to)] = ownerIndex; - OwnerChanged(_from, _to); - } - - function addOwner(address _owner) onlymanyowners(sha3(msg.data)) external { - if (isOwner(_owner)) return; - - clearPending(); - if (m_numOwners >= c_maxOwners) - reorganizeOwners(); - if (m_numOwners >= c_maxOwners) - return; - m_numOwners++; - m_owners[m_numOwners] = uint(_owner); - m_ownerIndex[uint(_owner)] = m_numOwners; - OwnerAdded(_owner); - } - - function removeOwner(address _owner) onlymanyowners(sha3(msg.data)) external { - uint ownerIndex = m_ownerIndex[uint(_owner)]; - if (ownerIndex == 0) return; - if (m_required > m_numOwners - 1) return; - - m_owners[ownerIndex] = 0; - m_ownerIndex[uint(_owner)] = 0; - clearPending(); - reorganizeOwners(); //make sure m_numOwner is equal to the number of owners and always points to the optimal free slot - OwnerRemoved(_owner); - } - - function changeRequirement(uint _newRequired) onlymanyowners(sha3(msg.data)) external { - if (_newRequired > m_numOwners) return; - m_required = _newRequired; - clearPending(); - RequirementChanged(_newRequired); - } - - // Gets an owner by 0-indexed position (using numOwners as the count) - function getOwner(uint ownerIndex) external constant returns (address) { - return address(m_owners[ownerIndex + 1]); - } - - function isOwner(address _addr) returns (bool) { - return m_ownerIndex[uint(_addr)] > 0; - } - - function hasConfirmed(bytes32 _operation, address _owner) constant returns (bool) { - var pending = m_pending[_operation]; - uint ownerIndex = m_ownerIndex[uint(_owner)]; - - // make sure they're an owner - if (ownerIndex == 0) return false; - - // determine the bit to set for this owner. - uint ownerIndexBit = 2**ownerIndex; - return !(pending.ownersDone & ownerIndexBit == 0); - } - - // INTERNAL METHODS - - function confirmAndCheck(bytes32 _operation) internal returns (bool) { - // determine what index the present sender is: - uint ownerIndex = m_ownerIndex[uint(msg.sender)]; - // make sure they're an owner - if (ownerIndex == 0) return; - - var pending = m_pending[_operation]; - // if we're not yet working on this operation, switch over and reset the confirmation status. - if (pending.yetNeeded == 0) { - // reset count of confirmations needed. - pending.yetNeeded = m_required; - // reset which owners have confirmed (none) - set our bitmap to 0. - pending.ownersDone = 0; - pending.index = m_pendingIndex.length++; - m_pendingIndex[pending.index] = _operation; - } - // determine the bit to set for this owner. - uint ownerIndexBit = 2**ownerIndex; - // make sure we (the message sender) haven't confirmed this operation previously. - if (pending.ownersDone & ownerIndexBit == 0) { - Confirmation(msg.sender, _operation); - // ok - check if count is enough to go ahead. - if (pending.yetNeeded <= 1) { - // enough confirmations: reset and run interior. - delete m_pendingIndex[m_pending[_operation].index]; - delete m_pending[_operation]; - return true; - } - else - { - // not enough: record that this owner in particular confirmed. - pending.yetNeeded--; - pending.ownersDone |= ownerIndexBit; - } - } - } - - function reorganizeOwners() private { - uint free = 1; - while (free < m_numOwners) - { - while (free < m_numOwners && m_owners[free] != 0) free++; - while (m_numOwners > 1 && m_owners[m_numOwners] == 0) m_numOwners--; - if (free < m_numOwners && m_owners[m_numOwners] != 0 && m_owners[free] == 0) - { - m_owners[free] = m_owners[m_numOwners]; - m_ownerIndex[m_owners[free]] = free; - m_owners[m_numOwners] = 0; - } - } - } - - function clearPending() internal { - uint length = m_pendingIndex.length; - for (uint i = 0; i < length; ++i) - if (m_pendingIndex[i] != 0) - delete m_pending[m_pendingIndex[i]]; - delete m_pendingIndex; - } - - // FIELDS - - // the number of owners that must confirm the same operation before it is run. - uint public m_required; - // pointer used to find a free slot in m_owners - uint public m_numOwners; - - // list of owners - uint[256] m_owners; - uint constant c_maxOwners = 250; - // index on the list of owners to allow reverse lookup - mapping(uint => uint) m_ownerIndex; - // the ongoing operations. - mapping(bytes32 => PendingState) m_pending; - bytes32[] m_pendingIndex; -} - -// inheritable "property" contract that enables methods to be protected by placing a linear limit (specifiable) -// on a particular resource per calendar day. is multiowned to allow the limit to be altered. resource that method -// uses is specified in the modifier. -contract daylimit is multiowned { - - // MODIFIERS - - // simple modifier for daily limit. - modifier limitedDaily(uint _value) { - if (underLimit(_value)) - _ - } - - // METHODS - - // constructor - stores initial daily limit and records the present day's index. - function daylimit(uint _limit) { - m_dailyLimit = _limit; - m_lastDay = today(); - } - // (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today. - function setDailyLimit(uint _newLimit) onlymanyowners(sha3(msg.data)) external { - m_dailyLimit = _newLimit; - } - // resets the amount already spent today. needs many of the owners to confirm. - function resetSpentToday() onlymanyowners(sha3(msg.data)) external { - m_spentToday = 0; - } - - // INTERNAL METHODS - - // checks to see if there is at least `_value` left from the daily limit today. if there is, subtracts it and - // returns true. otherwise just returns false. - function underLimit(uint _value) internal onlyowner returns (bool) { - // reset the spend limit if we're on a different day to last time. - if (today() > m_lastDay) { - m_spentToday = 0; - m_lastDay = today(); - } - // check to see if there's enough left - if so, subtract and return true. - // overflow protection // dailyLimit check - if (m_spentToday + _value >= m_spentToday && m_spentToday + _value <= m_dailyLimit) { - m_spentToday += _value; - return true; - } - return false; - } - // determines today's index. - function today() private constant returns (uint) { return now / 1 days; } - - // FIELDS - - uint public m_dailyLimit; - uint public m_spentToday; - uint public m_lastDay; -} - -// interface contract for multisig proxy contracts; see below for docs. -contract multisig { - - // EVENTS - - // logged events: - // Funds has arrived into the wallet (record how much). - event Deposit(address _from, uint value); - // Single transaction going out of the wallet (record who signed for it, how much, and to whom it's going). - event SingleTransact(address owner, uint value, address to, bytes data); - // Multi-sig transaction going out of the wallet (record who signed for it last, the operation hash, how much, and to whom it's going). - event MultiTransact(address owner, bytes32 operation, uint value, address to, bytes data); - // Confirmation still needed for a transaction. - event ConfirmationNeeded(bytes32 operation, address initiator, uint value, address to, bytes data); - - // FUNCTIONS - - // TODO: document - function changeOwner(address _from, address _to) external; - function execute(address _to, uint _value, bytes _data) external returns (bytes32); - function confirm(bytes32 _h) returns (bool); -} - -// usage: -// bytes32 h = Wallet(w).from(oneOwner).transact(to, value, data); -// Wallet(w).from(anotherOwner).confirm(h); -contract Wallet is multisig, multiowned, daylimit { - - // TYPES - - // Transaction structure to remember details of transaction lest it need be saved for a later call. - struct Transaction { - address to; - uint value; - bytes data; - } - - // METHODS - - // constructor - just pass on the owner array to the multiowned and - // the limit to daylimit - function Wallet(address[] _owners, uint _required, uint _daylimit) - multiowned(_owners, _required) daylimit(_daylimit) { - } - - // kills the contract sending everything to `_to`. - function kill(address _to) onlymanyowners(sha3(msg.data)) external { - suicide(_to); - } - - // gets called when no other function matches - function() { - // just being sent some cash? - if (msg.value > 0) - Deposit(msg.sender, msg.value); - } - - // Outside-visible transact entry point. Executes transaction immediately if below daily spend limit. - // If not, goes into multisig process. We provide a hash on return to allow the sender to provide - // shortcuts for the other confirmations (allowing them to avoid replicating the _to, _value - // and _data arguments). They still get the option of using them if they want, anyways. - function execute(address _to, uint _value, bytes _data) external onlyowner returns (bytes32 _r) { - // first, take the opportunity to check that we're under the daily limit. - if (underLimit(_value)) { - SingleTransact(msg.sender, _value, _to, _data); - // yes - just execute the call. - _to.call.value(_value)(_data); - return 0; - } - // determine our operation hash. - _r = sha3(msg.data, block.number); - if (!confirm(_r) && m_txs[_r].to == 0) { - m_txs[_r].to = _to; - m_txs[_r].value = _value; - m_txs[_r].data = _data; - ConfirmationNeeded(_r, msg.sender, _value, _to, _data); - } - } - - // confirm a transaction through just the hash. we use the previous transactions map, m_txs, in order - // to determine the body of the transaction from the hash provided. - function confirm(bytes32 _h) onlymanyowners(_h) returns (bool) { - if (m_txs[_h].to != 0) { - m_txs[_h].to.call.value(m_txs[_h].value)(m_txs[_h].data); - MultiTransact(msg.sender, _h, m_txs[_h].value, m_txs[_h].to, m_txs[_h].data); - delete m_txs[_h]; - return true; - } - } - - // INTERNAL METHODS - - function clearPending() internal { - uint length = m_pendingIndex.length; - for (uint i = 0; i < length; ++i) - delete m_txs[m_pendingIndex[i]]; - super.clearPending(); - } - - // FIELDS - - // pending transactions we have at present. - mapping (bytes32 => Transaction) m_txs; -} diff --git a/src/clj/commiteth/eth/core.clj b/src/clj/commiteth/eth/core.clj index a6639a2..52594be 100644 --- a/src/clj/commiteth/eth/core.clj +++ b/src/clj/commiteth/eth/core.clj @@ -13,17 +13,16 @@ (defn eth-rpc [method params] - (let [body (json/write-str {:jsonrpc "2.0" - :method method - :params params - :id 1}) - options {:body body} - result (:body @(post eth-rpc-url options))] - (:result (json/read-str result :key-fn keyword)))) - -(defn compile-solidity - [source] - (eth-rpc "eth_compileSolidity" [source])) + (let [body (json/write-str {:jsonrpc "2.0" + :method method + :params params + :id 1}) + options {:body body} + response (:body @(post eth-rpc-url options)) + result (json/read-str response :key-fn keyword)] + (when-let [error (:error result)] + (log/error "Method: " method ", error: " error)) + (:result result))) (defn send-transaction [from to value & [params]] @@ -38,10 +37,7 @@ (defn deploy-contract [] - (let [contract-src (-> "sol/wallet.sol" io/resource slurp) - contract-name :Wallet - contract-data (compile-solidity contract-src) - contract-code (get-in contract-data [contract-name :code])] + (let [contract-code (-> "contracts/wallet.data" io/resource slurp)] (send-transaction (eth-account) nil 1 {:gas "1248650" :data contract-code})))