Last active
August 7, 2019 21:50
-
-
Save nealmcb/8be0133f1bc4a77dcc7a6f5b9e25f017 to your computer and use it in GitHub Desktop.
Civil Transparency Experiments in Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "cells": [ | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "# Civil Transparency Experiments in Python\n", | |
| "\n", | |
| "Exploring and auditing the https://civil.co world and ecosystem for higher-quality, more sustainable journalism.\n", | |
| "\n", | |
| "As discussed at https://community.civil.co/t/transparency-reproducible-vote-tallies-etc-digging-in-to-the-blockchain/147\n", | |
| "\n", | |
| "So far, this is just the beginning of getting on board in Python with Ethereum, web3, Civil, PLCR etc.\n", | |
| "so we can e.g. some day audit the vote counts announced to the community." | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "## Preparation\n", | |
| "\n", | |
| "Do this, ideally in a virtual environment, before starting up your Jupyter notebook or python3 environment:\n", | |
| "\n", | |
| "Learn about Ethereum in Python:\n", | |
| "[Ethereum Smart Contracts in Python: a comprehensive(ish) guide](https://hackernoon.com/ethereum-smart-contracts-in-python-a-comprehensive-ish-guide-771b03990988)\n", | |
| "\n", | |
| "`pip install web3 ens jupyter`\n", | |
| "\n", | |
| "Install a local eth server, or get keys to connect to the eth network via https://infura.io or whatever.\n", | |
| "\n", | |
| "`export WEB3_INFURA_API_KEY=xxxx`\n", | |
| "\n", | |
| "`export WEB3_PROVIDER_URI=wss://mainnet.infura.io/ws/v3/xxxx`" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 1, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "import json\n", | |
| "import urllib.request\n", | |
| "from web3 import Web3\n", | |
| "from web3.auto import w3\n", | |
| "from ens import ENS" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 2, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "8274358" | |
| ] | |
| }, | |
| "execution_count": 2, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "w3.eth.blockNumber" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 3, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "ns = ENS.fromWeb3(w3) \n", | |
| "cvltcr = ns.address('civiltcr.eth')" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 4, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "'0xBd5a95A66dd4E78Bcb597198Df222c4EdDC14DA7'" | |
| ] | |
| }, | |
| "execution_count": 4, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "cvltcr" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 5, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "True" | |
| ] | |
| }, | |
| "execution_count": 5, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "cvltcr == Web3.toChecksumAddress(cvltcr)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 6, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "'0x00c26eC65d2D84667212b820bfd25C60b59c60f5'" | |
| ] | |
| }, | |
| "execution_count": 6, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "ns.owner('civiltcr')" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 7, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "ctcr = json.loads(urllib.request.urlopen('https://raw.githubusercontent.com/joincivil/Civil/master/packages/artifacts/v1/CivilTCR.json').read())" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 9, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "cabi = ctcr['abi']\n", | |
| "cvl = w3.eth.contract(address=cvltcr, abi=cabi)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 10, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "'CivilTCR'" | |
| ] | |
| }, | |
| "execution_count": 10, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "cvl.functions.name().call() " | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 11, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "['name', 'civilVoting', 'government', 'parameterizer', 'token', 'voting']" | |
| ] | |
| }, | |
| "execution_count": 11, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "[c['name'] for c in cabi if 'name' in c and c['inputs'] == []]" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 12, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "'0xc625FC42ab6d07746b953aE98b4Ec22622E1B9A9'" | |
| ] | |
| }, | |
| "execution_count": 12, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "cvl.functions.government().call()" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 13, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "'0x55656b8a58dF94C1e8B5142F8da973301452eA65'" | |
| ] | |
| }, | |
| "execution_count": 13, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "cvl.functions.civilVoting().call()" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 14, | |
| "metadata": { | |
| "scrolled": true | |
| }, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "['name',\n", | |
| " 'civilVoting',\n", | |
| " 'government',\n", | |
| " 'isWhitelisted',\n", | |
| " 'deposit',\n", | |
| " 'claimRewards',\n", | |
| " 'appWasMade',\n", | |
| " 'challengeRequestAppealExpiries',\n", | |
| " 'listings',\n", | |
| " 'challengeExists',\n", | |
| " 'challenges',\n", | |
| " 'tokenClaims',\n", | |
| " 'appeals',\n", | |
| " 'exit',\n", | |
| " 'canBeWhitelisted',\n", | |
| " 'parameterizer',\n", | |
| " 'withdraw',\n", | |
| " 'updateStatuses',\n", | |
| " 'token',\n", | |
| " 'voting',\n", | |
| " '_AppealRequested',\n", | |
| " '_AppealGranted',\n", | |
| " '_FailedChallengeOverturned',\n", | |
| " '_SuccessfulChallengeOverturned',\n", | |
| " '_GrantedAppealChallenged',\n", | |
| " '_GrantedAppealOverturned',\n", | |
| " '_GrantedAppealConfirmed',\n", | |
| " '_GovernmentTransfered',\n", | |
| " '_Application',\n", | |
| " '_Challenge',\n", | |
| " '_Deposit',\n", | |
| " '_Withdrawal',\n", | |
| " '_ApplicationWhitelisted',\n", | |
| " '_ApplicationRemoved',\n", | |
| " '_ListingRemoved',\n", | |
| " '_ListingWithdrawn',\n", | |
| " '_TouchAndRemoved',\n", | |
| " '_ChallengeFailed',\n", | |
| " '_ChallengeSucceeded',\n", | |
| " '_RewardClaimed',\n", | |
| " 'apply',\n", | |
| " 'requestAppeal',\n", | |
| " 'grantAppeal',\n", | |
| " 'transferGovernment',\n", | |
| " 'updateStatus',\n", | |
| " 'challenge',\n", | |
| " 'challengeGrantedAppeal',\n", | |
| " 'claimReward',\n", | |
| " 'determineReward',\n", | |
| " 'voterReward',\n", | |
| " 'challengeCanBeResolved',\n", | |
| " 'appealCanBeResolved',\n", | |
| " 'appealChallengeCanBeResolved']" | |
| ] | |
| }, | |
| "execution_count": 14, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "[c['name'] for c in cabi if 'name' in c]" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 15, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "cplcr = json.loads(urllib.request.urlopen('https://raw.githubusercontent.com/joincivil/Civil/master/packages/artifacts/v1/CivilPLCRVoting.json').read())" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 16, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "cplcrabi = cplcr['abi']" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 17, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "['INITIAL_POLL_NONCE', 'telemetry', 'pollNonce', 'token']" | |
| ] | |
| }, | |
| "execution_count": 17, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "[c['name'] for c in cplcrabi if 'name' in c and c['inputs'] == []]" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 18, | |
| "metadata": { | |
| "scrolled": true | |
| }, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "['getTotalNumberOfTokensForWinningOption',\n", | |
| " 'INITIAL_POLL_NONCE',\n", | |
| " 'getInsertPointForNumTokens',\n", | |
| " 'startPoll',\n", | |
| " 'voteTokenBalance',\n", | |
| " 'commitVotes',\n", | |
| " 'telemetry',\n", | |
| " 'getLastNode',\n", | |
| " 'revealPeriodActive',\n", | |
| " 'isPassed',\n", | |
| " 'pollMap',\n", | |
| " 'getLockedTokens',\n", | |
| " 'commitVote',\n", | |
| " 'didCommit',\n", | |
| " 'revealVotes',\n", | |
| " 'validPosition',\n", | |
| " 'pollExists',\n", | |
| " 'pollNonce',\n", | |
| " 'rescueTokens',\n", | |
| " 'attrUUID',\n", | |
| " 'commitPeriodActive',\n", | |
| " 'didReveal',\n", | |
| " 'revealVote',\n", | |
| " 'getNumPassingTokens',\n", | |
| " 'rescueTokensInMultiplePolls',\n", | |
| " 'getNumTokens',\n", | |
| " 'getCommitHash',\n", | |
| " 'isExpired',\n", | |
| " 'withdrawVotingRights',\n", | |
| " 'pollEnded',\n", | |
| " 'token',\n", | |
| " '_VoteCommitted',\n", | |
| " '_VoteRevealed',\n", | |
| " '_PollCreated',\n", | |
| " '_VotingRightsGranted',\n", | |
| " '_VotingRightsWithdrawn',\n", | |
| " '_TokensRescued',\n", | |
| " 'requestVotingRights',\n", | |
| " 'getNumLosingTokens',\n", | |
| " 'getTotalNumberOfTokensForLosingOption']" | |
| ] | |
| }, | |
| "execution_count": 18, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "[c['name'] for c in cplcrabi if 'name' in c]" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "## Look at a challenged newsroom\n", | |
| "\n", | |
| "`mmviii [2008]`: https://registry.civil.co/listing/0xfcd4bd67481b8ffb9682988ef73dd72cf64dc0ae\n", | |
| "\n", | |
| "Blockchain Trailblazers: \n", | |
| "https://registry.civil.co/listing/0x49db84c3dbea7240293c7cd943827d59a8dc766b" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 19, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "mmvii = Web3.toInt(hexstr='0xfcd4bd67481b8ffb9682988ef73dd72cf64dc0ae')" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 20, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "[0, '0x0000000000000000000000000000000000000000', False, 0, 0]" | |
| ] | |
| }, | |
| "execution_count": 20, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "cvl.functions.challenges(mmvii).call()" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 21, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "[0, '0x0000000000000000000000000000000000000000', False, 0, 0]" | |
| ] | |
| }, | |
| "execution_count": 21, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "trailbl = Web3.toInt(hexstr='0x49db84c3dbea7240293c7cd943827d59a8dc766b')\n", | |
| "cvl.functions.challenges(trailbl).call()" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "And an approved newsroom:\n", | |
| "\n", | |
| "Africa-OnTheRise: https://registry.civil.co/listing/0x6af6e3e92a5c68e155f493f9671e0d4a5a01a002" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 23, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "[0, '0x0000000000000000000000000000000000000000', False, 0, 0]" | |
| ] | |
| }, | |
| "execution_count": 23, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "cvl.functions.challenges(Web3.toInt(hexstr='0x6af6e3e92a5c68e155f493f9671e0d4a5a01a002')).call()" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "## Now what?\n", | |
| "\n", | |
| "Read more tips at https://community.civil.co/t/transparency-reproducible-vote-tallies-etc-digging-in-to-the-blockchain/147 ..." | |
| ] | |
| } | |
| ], | |
| "metadata": { | |
| "kernelspec": { | |
| "display_name": "Python 3", | |
| "language": "python", | |
| "name": "python3" | |
| }, | |
| "language_info": { | |
| "codemirror_mode": { | |
| "name": "ipython", | |
| "version": 3 | |
| }, | |
| "file_extension": ".py", | |
| "mimetype": "text/x-python", | |
| "name": "python", | |
| "nbconvert_exporter": "python", | |
| "pygments_lexer": "ipython3", | |
| "version": "3.6.8" | |
| }, | |
| "toc": { | |
| "colors": { | |
| "hover_highlight": "#DAA520", | |
| "running_highlight": "#FF0000", | |
| "selected_highlight": "#FFD700" | |
| }, | |
| "moveMenuLeft": true, | |
| "nav_menu": { | |
| "height": "63px", | |
| "width": "252px" | |
| }, | |
| "navigate_menu": true, | |
| "number_sections": true, | |
| "sideBar": true, | |
| "threshold": 4, | |
| "toc_cell": false, | |
| "toc_section_display": "block", | |
| "toc_window_display": false, | |
| "widenNotebook": false | |
| } | |
| }, | |
| "nbformat": 4, | |
| "nbformat_minor": 2 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment