accounts-index

Accounts index evm contract tooling with permissioned writes
Log | Files | Refs

commit 9e91b74fd0f8a91c9cb519914ef3a5e826b476b9
parent a230b59ffb59fc83ea477f221557ef3897889315
Author: nolash <dev@holbrook.no>
Date:   Tue,  1 Dec 2020 23:51:17 +0100

Add dockerfile

Diffstat:
ADockerfile | 28++++++++++++++++++++++++++++
Apython/CHANGELOG | 4++++
Apython/LICENSE | 45+++++++++++++++++++++++++++++++++++++++++++++
Apython/MANIFEST.in | 1+
Apython/eth_accounts_index/runnable/deploy.py | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mpython/setup.cfg | 7++++++-
Rsolidity/registry.abi.json -> solidity/AccountsIndex.abi.json | 0
Rsolidity/registry.bin -> solidity/AccountsIndex.bin | 0
Asolidity/AccountsIndex.sol | 39+++++++++++++++++++++++++++++++++++++++
Dsolidity/deploy.py | 94-------------------------------------------------------------------------------
Dsolidity/registry.sol | 39---------------------------------------
11 files changed, 223 insertions(+), 134 deletions(-)

diff --git a/Dockerfile b/Dockerfile @@ -0,0 +1,28 @@ +FROM ethereum/solc:0.6.12 + +FROM python:3.8.6-alpine + +COPY --from=0 /usr/bin/solc /usr/bin/solc + +RUN apk update &&\ + apk add gcc bash musl-dev + +WORKDIR /usr/src + +# Try to keep everything above here re-usable! + +COPY ./solidity/ /usr/src/eth_accounts_index/solidity/ +COPY ./python/ /usr/src/eth_accounts_index/python/ + +RUN cd eth_accounts_index/solidity && \ + solc AccountsIndex.sol --abi | awk 'NR>3' > AccountsIndex.abi.json + +RUN cd eth_accounts_index/solidity && \ + solc AccountsIndex.sol --bin | awk 'NR>3' > AccountsIndex.bin && \ + truncate -s "$((`stat -t -c "%s" AccountsIndex.bin`-1))" AccountsIndex.bin + +RUN cd eth_accounts_index/python && \ + pip install --extra-index-url https://pip.grassrootseconomics.net:8433 . + +# To deploy: +# eth-accounts-index --contracts-dir eth_accounts_index/solidity/ [...] diff --git a/python/CHANGELOG b/python/CHANGELOG @@ -0,0 +1,4 @@ +- 0.0.2 + * Move deploy script to within setup +- 0.0.1 + * Simple solidity method wrapper diff --git a/python/LICENSE b/python/LICENSE @@ -0,0 +1,45 @@ + Bprotocol Foundation (Bancor) LICENSE + +1. SUBJECT TO THE PROVISIONS SET FORTH HEREIN, INCLUDING “EFFECTIVE DATE”, YOU CAN + USE THIS CODE, FILE AND/OR SOFTWARE (“SOFTWARE”) ONLY IN CONNECTION WITH THE + BANCOR LIQUIDITY NETWORK AND/OR THE USE OF BNT ("PERMITTED USE"). ANY OTHER USE IS + PROHIBITED UNLESS THE USER SHALL RECEIVE AN EXPLICIT PRIOR WRITTEN APPROVAL FROM + BPROTOCOL FOUNDATION (BANCOR) TO DO SO (PLEASE CONTACT license@bancor.network IN + THIS REGARD), WHICH APPROVAL, IF GIVEN, MAY REQUIRE THE OBTAINMENT OF SEPARATE + LICENSE UNDER A DIFFERENT LICENSING MODEL. USING THIS SOFTWARE NOT IN THE FRAME OF + SUCH PERMITTED USE MAY, AMONG OTHERS, ALSO BREACH PATENT RIGHTS CONCERNING PATENTS + WHICH ARE EMBODIED/INCORPORATED/USED IN THIS SOFTWARE. + +2. ANY SUCH PERMITTED USE SHOULD ALSO COMPLY WITH THE TERMS BELOW. + +3. Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: +A. Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. +B. Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. +C. Neither the name of the copyright holder nor the names of its contributors may be + used to endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +EFFECTIVE DATE: THIS LICENSE SHALL APPLY ONLY TO SOFTWARE (OR ANY VERSION THEREOF), +THAT HAS BEEN PUBLISHED AFTER THE DATE AND TIME THIS LICENSE HAS BEEN FIRST PUBLISHED +(“EFFECTIVE DATE”); Any previous versions published prior to the effective date (“Older Versions”) +shall remain licensed under the Apache License, Version 2.0 (the "Older Versions License"); +You may obtain a copy of the Older Version License at http://www.apache.org/licenses/LICENSE-2.0 +you may not use this file except in compliance with the Older Version License. Unless +required by applicable law or agreed to in writing, Older Versions distributed under the +Older Version License are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS +OF ANY KIND, either express or implied. See the Older Version License for the specific +language governing permissions and limitations under the Older Version License. diff --git a/python/MANIFEST.in b/python/MANIFEST.in @@ -0,0 +1 @@ +include **/*.abi.json diff --git a/python/eth_accounts_index/runnable/deploy.py b/python/eth_accounts_index/runnable/deploy.py @@ -0,0 +1,100 @@ +"""Deploys accounts index, registering arbitrary number of writers + +.. moduleauthor:: Louis Holbrook <dev@holbrook.no> +.. pgp:: 0826EDA1702D1E87C6E2875121D2E7BB88C2A746 + +""" + +# standard imports +import os +import json +import argparse +import logging + +# third-party imports +import web3 + + +logging.basicConfig(level=logging.WARNING) +logg = logging.getLogger() + +logging.getLogger('web3').setLevel(logging.WARNING) +logging.getLogger('urllib3').setLevel(logging.WARNING) + +argparser = argparse.ArgumentParser() +argparser.add_argument('-p', '--provider', dest='p', default='http://localhost:8545', type=str, help='Web3 provider url (http only)') +argparser.add_argument('-w', '--writer', dest='w', action='append', type=str, help='Writer to add') +argparser.add_argument('-a', '--account', dest='a', action='append', type=str, help='Account to add') +argparser.add_argument('-k', '--keep-sender', dest='k', action='store_true', help='If set, sender will be kept as writer') +argparser.add_argument('--contracts-dir', dest='contracts_dir', default='.', help='Directory containing bytecode and abi') +argparser.add_argument('-v', action='store_true', help='Be verbose') +args = argparser.parse_args() + +if args.v: + logg.setLevel(logging.DEBUG) + +def main(): + w3 = web3.Web3(web3.Web3.HTTPProvider(args.p)) + + f = open(os.path.join(args.contracts_dir, 'AccountsIndex.abi.json'), 'r') + abi = json.load(f) + f.close() + + f = open(os.path.join(args.contracts_dir, 'AccountsIndex.bin'), 'r') + bytecode = f.read() + f.close() + + w3.eth.defaultAccount = w3.eth.accounts[0] + + c = w3.eth.contract(abi=abi, bytecode=bytecode) + tx_hash = c.constructor().transact({'from': w3.eth.accounts[0]}) + + rcpt = w3.eth.getTransactionReceipt(tx_hash) + + address = rcpt.contractAddress + c = w3.eth.contract(abi=abi, address=address) + + logg.debug('adding sender to write list') + c.functions.addWriter(w3.eth.accounts[0]).transact() + + if args.w != None: + for w in args.w: + logg.info('adding {} to write list'.format(w)) + c.functions.addWriter(w).transact() + + if args.a != None: + for a in args.a: + logg.info('adding {} to accounts index'.format(a)) + c.functions.add(a).transact() + + if not args.k: + logg.debug('deleting sender for write list') + c.functions.deleteWriter(w3.eth.accounts[0]).transact() + + print(address) + +# fail = False +# try: +# c.functions.add(w3.eth.accounts[2]).transact({'from': w3.eth.accounts[1]}) +# except: +# fail = True +# assert fail +# +# c.functions.addWriter(w3.eth.accounts[1]).transact({'from': w3.eth.accounts[0]}) +# c.functions.add(w3.eth.accounts[2]).transact({'from': w3.eth.accounts[1]}) +# c.functions.add(w3.eth.accounts[3]).transact({'from': w3.eth.accounts[1]}) +# +# assert c.functions.count().call() == 3 +# assert c.functions.accountsIndex(w3.eth.accounts[3]).call() == 2 +# assert c.functions.accounts(2).call() == w3.eth.accounts[3] +# +# fail = False +# try: +# c.functions.add(w3.eth.accounts[3]).transact({'from': w3.eth.accounts[1]}) +# except: +# fail = True +# assert fail + + +if __name__ == '__main__': + main() diff --git a/python/setup.cfg b/python/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = eth-accounts-index -version = 0.0.2 +version = 0.0.3 description = Accounts index evm contract tooling with permissioned writes author = Louis Holbrook author_email = dev@holbrook.no @@ -25,9 +25,14 @@ include_package_data = True python_requires = >= 3.6 packages = eth_accounts_index + eth_accounts_index.runnable install_requires = confini==0.3.1 web3==5.12.2 [options.package_data] * = **/*.abi.json + +[options.entry_points] +console_scripts = + accounts-index-deploy = eth_accounts_index.runnable.deploy:main diff --git a/solidity/registry.abi.json b/solidity/AccountsIndex.abi.json diff --git a/solidity/registry.bin b/solidity/AccountsIndex.bin diff --git a/solidity/AccountsIndex.sol b/solidity/AccountsIndex.sol @@ -0,0 +1,39 @@ +pragma solidity ^0.6.12; + +// SPDX-License-Identifier: GPL-3.0-or-later + +contract CustodialAccountIndex { + + address[] public accounts; + mapping(address => uint256) public accountsIndex; + uint256 public count; + mapping(address => bool) writers; + address owner; + + event AccountAdded(address indexed addedAccount, uint256 indexed accountIndex); + + constructor() public { + owner = msg.sender; + accounts.push(address(0)); + count = 1; + } + + function addWriter(address _writer) public { + require(owner == msg.sender); + writers[_writer] = true; + } + + function deleteWriter(address _writer) public { + require(owner == msg.sender); + delete writers[_writer]; + } + + function add(address _account) public { + require(writers[msg.sender]); + require(accountsIndex[_account] == 0); + accounts.push(_account); + accountsIndex[_account] = count; + count++; + emit AccountAdded(_account, count-1); + } +} diff --git a/solidity/deploy.py b/solidity/deploy.py @@ -1,94 +0,0 @@ -"""Deploys accounts index, registering arbitrary number of writers - -.. moduleauthor:: Louis Holbrook <dev@holbrook.no> -.. pgp:: 0826EDA1702D1E87C6E2875121D2E7BB88C2A746 - -""" - -# standard imports -import json -import argparse -import logging - -# third-party imports -import web3 - - -logging.basicConfig(level=logging.WARNING) -logg = logging.getLogger() - -logging.getLogger('web3').setLevel(logging.WARNING) -logging.getLogger('urllib3').setLevel(logging.WARNING) - -argparser = argparse.ArgumentParser() -argparser.add_argument('-p', '--provider', dest='p', default='http://localhost:8545', type=str, help='Web3 provider url (http only)') -argparser.add_argument('-w', '--writer', dest='w', action='append', type=str, help='Writer to add') -argparser.add_argument('-a', '--account', dest='a', action='append', type=str, help='Account to add') -argparser.add_argument('-k', '--keep-sender', dest='k', action='store_true', help='If set, sender will be kept as writer') -argparser.add_argument('-v', action='store_true', help='Be verbose') -args = argparser.parse_args() - -if args.v: - logg.setLevel(logging.DEBUG) - -if __name__ == '__main__': - w3 = web3.Web3(web3.Web3.HTTPProvider(args.p)) - - f = open('registry.bin', 'r') - bytecode = f.read() - f.close() - - f = open('registry.abi.json', 'r') - abi = json.load(f) - f.close() - - w3.eth.defaultAccount = w3.eth.accounts[0] - - c = w3.eth.contract(abi=abi, bytecode=bytecode) - tx_hash = c.constructor().transact({'from': w3.eth.accounts[0]}) - - rcpt = w3.eth.getTransactionReceipt(tx_hash) - - address = rcpt.contractAddress - c = w3.eth.contract(abi=abi, address=address) - - logg.debug('adding sender to write list') - c.functions.addWriter(w3.eth.accounts[0]).transact() - - if args.w != None: - for w in args.w: - logg.info('adding {} to write list'.format(w)) - c.functions.addWriter(w).transact() - - if args.a != None: - for a in args.a: - logg.info('adding {} to accounts index'.format(a)) - c.functions.add(a).transact() - - if not args.k: - logg.debug('deleting sender for write list') - c.functions.deleteWriter(w3.eth.accounts[0]).transact() - - print(address) - -# fail = False -# try: -# c.functions.add(w3.eth.accounts[2]).transact({'from': w3.eth.accounts[1]}) -# except: -# fail = True -# assert fail -# -# c.functions.addWriter(w3.eth.accounts[1]).transact({'from': w3.eth.accounts[0]}) -# c.functions.add(w3.eth.accounts[2]).transact({'from': w3.eth.accounts[1]}) -# c.functions.add(w3.eth.accounts[3]).transact({'from': w3.eth.accounts[1]}) -# -# assert c.functions.count().call() == 3 -# assert c.functions.accountsIndex(w3.eth.accounts[3]).call() == 2 -# assert c.functions.accounts(2).call() == w3.eth.accounts[3] -# -# fail = False -# try: -# c.functions.add(w3.eth.accounts[3]).transact({'from': w3.eth.accounts[1]}) -# except: -# fail = True -# assert fail diff --git a/solidity/registry.sol b/solidity/registry.sol @@ -1,39 +0,0 @@ -pragma solidity ^0.6.12; - -// SPDX-License-Identifier: GPL-3.0-or-later - -contract CustodialAccountIndex { - - address[] public accounts; - mapping(address => uint256) public accountsIndex; - uint256 public count; - mapping(address => bool) writers; - address owner; - - event AccountAdded(address indexed addedAccount, uint256 indexed accountIndex); - - constructor() { - owner = msg.sender; - accounts.push(address(0)); - count = 1; - } - - function addWriter(address _writer) public { - require(owner == msg.sender); - writers[_writer] = true; - } - - function deleteWriter(address _writer) public { - require(owner == msg.sender); - delete writers[_writer]; - } - - function add(address _account) public { - require(writers[msg.sender]); - require(accountsIndex[_account] == 0); - accounts.push(_account); - accountsIndex[_account] = count; - count++; - emit AccountAdded(_account, count-1); - } -}