diff --git a/.gitignore b/.gitignore index 2ff8c9e..ab2ba38 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,13 @@ .idea .deps .debugger +.vscode + +# python temporary files +__pycache__ +*.pyc +*.pyo +*.pyd artifacts/ diff --git a/PubSub/Makefile b/PubSub/Makefile index 3285cd9..98b120a 100644 --- a/PubSub/Makefile +++ b/PubSub/Makefile @@ -3,6 +3,8 @@ CONTRACTS := \ EventManager \ PubSubService +CHECKSUM_BIN := openssl sha256 + all: $(addprefix ../build/$(MODULE_NAME)/,$(addsuffix .abi,$(CONTRACTS))) \ $(addprefix ../build/$(MODULE_NAME)/,$(addsuffix .bin,$(CONTRACTS))) \ @@ -14,36 +16,38 @@ all: $(addprefix ../build/$(MODULE_NAME)/,$(addsuffix .abi,$(CONTRACTS))) \ ../build/$(MODULE_NAME)/%.bin: %.sol ../build/nodeenv.state - . ../build/nodeenv/bin/activate; \ - solcjs --optimize --optimize-runs 200 \ - --bin \ - --include-path node_modules/ --base-path .. \ - --output-dir ../build/$(MODULE_NAME)/ \ - $< && \ - mv ../build/$(MODULE_NAME)/$(MODULE_NAME)_$(basename $<)_sol_$(basename $<).bin \ - ../build/$(MODULE_NAME)/$(basename $<).bin && \ - rm -f ../build/$(MODULE_NAME)/*_sol_*.bin; \ - deactivate_node + ( \ + . ../build/nodeenv/bin/activate && \ + solcjs --optimize --optimize-runs 200 \ + --bin \ + --include-path node_modules/ --base-path .. \ + --output-dir ../build/$(MODULE_NAME)/ \ + $< && \ + mv ../build/$(MODULE_NAME)/$(MODULE_NAME)_$(basename $<)_sol_$(basename $<).bin \ + ../build/$(MODULE_NAME)/$(basename $<).bin && \ + rm -f ../build/$(MODULE_NAME)/*_sol_*.bin \ + ) ../build/$(MODULE_NAME)/%.abi: %.sol ../build/nodeenv.state - . ../build/nodeenv/bin/activate; \ - solcjs --optimize --optimize-runs 200 \ - --abi \ - --include-path node_modules/ --base-path .. \ - --output-dir ../build/$(MODULE_NAME)/ \ - $< && \ - mv ../build/$(MODULE_NAME)/$(MODULE_NAME)_$(basename $<)_sol_$(basename $<).abi \ - ../build/$(MODULE_NAME)/$(basename $<).abi && \ - rm -f ../build/$(MODULE_NAME)/*_sol_*.abi; \ - deactivate_node + ( \ + . ../build/nodeenv/bin/activate && \ + solcjs --optimize --optimize-runs 200 \ + --abi \ + --include-path node_modules/ --base-path .. \ + --output-dir ../build/$(MODULE_NAME)/ \ + $< && \ + mv ../build/$(MODULE_NAME)/$(MODULE_NAME)_$(basename $<)_sol_$(basename $<).abi \ + ../build/$(MODULE_NAME)/$(basename $<).abi && \ + rm -f ../build/$(MODULE_NAME)/*_sol_*.abi \ + ) ../build/$(MODULE_NAME)/checksums.txt: $(addprefix ../build/$(MODULE_NAME)/,$(addsuffix .abi,$(CONTRACTS))) \ $(addprefix ../build/$(MODULE_NAME)/,$(addsuffix .bin,$(CONTRACTS))) ( \ cd ../build/$(MODULE_NAME); \ - sha256sum $(addsuffix .abi,$(CONTRACTS)) $(addsuffix .bin,$(CONTRACTS)) > checksums.txt; \ + $(CHECKSUM_BIN) $(addsuffix .abi,$(CONTRACTS)) $(addsuffix .bin,$(CONTRACTS)) > checksums.txt; \ ) diff --git a/README.md b/README.md index 737bf2f..ebe4e83 100644 --- a/README.md +++ b/README.md @@ -15,18 +15,3 @@ Solidity code for the on-chain component of Decentagram project - run `make` command under project's root directory, and the generated binary files can be find under `build` directory - The `solc` compiler version can be configured in `utils/nodeenv-requirements.txt` - -# Ganache -## To start Ganache, create new keys, and add keys to keys directory: -``` -ganache-cli -a 20 --network-id 1337 --wallet.accountKeysPath [path_to_decent_lib]/decent-pubsub-onchain/eth_accounts/keys.json -``` -## Start Ganache with existing keys.json folder existing: -``` -ganache-cli -d -a 20 --network-id 1337 -``` -### Notes -``` --d = deterministic (deterministic private keys for testing) --a 20 = create 20 accounts -``` diff --git a/code/go/throughput-eval/go.mod b/code/go/throughput-eval/go.mod deleted file mode 100644 index 5409f8d..0000000 --- a/code/go/throughput-eval/go.mod +++ /dev/null @@ -1,25 +0,0 @@ -module throughput-test - -go 1.19 - -require ( - github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect - github.com/deckarep/golang-set/v2 v2.1.0 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect - github.com/ethereum/go-ethereum v1.11.3 // indirect - github.com/go-ole/go-ole v1.2.1 // indirect - github.com/go-stack/stack v1.8.1 // indirect - github.com/golang/snappy v0.0.4 // indirect - github.com/gorilla/websocket v1.4.2 // indirect - github.com/huin/goupnp v1.0.3 // indirect - github.com/jackpal/go-nat-pmp v1.0.2 // indirect - github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect - github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect - github.com/tklauser/go-sysconf v0.3.5 // indirect - github.com/tklauser/numcpus v0.2.2 // indirect - golang.org/x/crypto v0.1.0 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.5.0 // indirect - gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect -) diff --git a/code/go/throughput-eval/go.sum b/code/go/throughput-eval/go.sum deleted file mode 100644 index ab2d574..0000000 --- a/code/go/throughput-eval/go.sum +++ /dev/null @@ -1,144 +0,0 @@ -github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= -github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= -github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= -github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoGMWEhDvS3zToKcDpRsLuRolQJBVGdozk= -github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= -github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= -github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= -github.com/ethereum/go-ethereum v1.11.3 h1:uuBkYUJW9aY5JYi3+sqLHz+XWyo5fmn/ab9XcbtVDTU= -github.com/ethereum/go-ethereum v1.11.3/go.mod h1:rBUvAl5cdVrAei9q5lgOU7RSEuPJk1nlBDnS/YSoKQE= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= -github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= -github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= -github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= -github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= -github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw= -github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= -github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= -github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= -github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= -github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= -github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= -github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= -github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= -github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= -github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= -github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= -github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= -github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/time v0.0.0-20220922220347-f3bd1da661af h1:Yx9k8YCG3dvF87UAn2tu2HQLf2dt/eR1bXxpLMWeH+Y= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/code/go/throughput-eval/main.go b/code/go/throughput-eval/main.go deleted file mode 100644 index fec4572..0000000 --- a/code/go/throughput-eval/main.go +++ /dev/null @@ -1,354 +0,0 @@ -package main - -import ( - "bytes" - "context" - "encoding/binary" - "encoding/json" - "fmt" - "math/big" - "net/http" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/rlp" -) - -const ( - STARTBLOCK = 8627000 - ENDBLOCK = 8629000 - LOCAL_ENDPOINT = "http://127.0.0.1:8545/" -) - -var ( - BlockNums []string - RlpResp map[string]interface{} - - EthBlock *types.Block - EthHeader *types.Header - - HeaderRlpResp string -) - -type PayloadBlock struct { - Method string `json:"method"` - Params []any `json:"params"` - ID int `json:"id"` - Jsonrpc string `json:"jsonrpc"` -} - -func PanicIfError(err error) { - if err != nil { - panic(err) - } -} - -func GenerateBlockNums() { - for i := STARTBLOCK; i < ENDBLOCK; i++ { - BlockNums = append(BlockNums, fmt.Sprintf("0x%x", i)) - } -} - -// bloomValues is a private function in geth I've copied it and added in some print statements to show you how it works -// See here for function in geth codebase https://github.com/ethereum/go-ethereum/blob/d8ff53dfb8a516f47db37dbc7fd7ad18a1e8a125/core/types/bloom9.go#L139 -func bloomValues(data []byte, hashbuf []byte) (uint, byte, uint, byte, uint, byte) { - var hashed = crypto.Keccak256(data) - hashbuf = hashed[:6] - - // The actual bits to flip - v1 := byte(1 << (hashbuf[1] & 0x7)) - v2 := byte(1 << (hashbuf[3] & 0x7)) - v3 := byte(1 << (hashbuf[5] & 0x7)) - - // The indices for the bytes to OR in - i1 := types.BloomByteLength - uint((binary.BigEndian.Uint16(hashbuf)&0x7ff)>>3) - 1 - i2 := types.BloomByteLength - uint((binary.BigEndian.Uint16(hashbuf[2:])&0x7ff)>>3) - 1 - i3 := types.BloomByteLength - uint((binary.BigEndian.Uint16(hashbuf[4:])&0x7ff)>>3) - 1 - - return i1, v1, i2, v2, i3, v3 -} - -func CheckBloomBits(bloom []byte, data ...[]byte) bool { - buf := make([]byte, 6) - var i1, i2, i3 uint - var v1, v2, v3 byte - - for _, d := range data { - i1, v1, i2, v2, i3, v3 = bloomValues(d, buf) - inBloom := (bloom[i1]&v1 != 0 && bloom[i2]&v2 != 0 && bloom[i3]&v3 != 0) - if !inBloom { - return false - } - } - return true -} - -func StringToBytes(str string) []byte { - str = str[2:] - strBytes := common.FromHex(str) - - return strBytes -} - -func ExecuteRequest(requestBody *bytes.Reader) map[string]interface{} { - req, _ := http.NewRequest("POST", LOCAL_ENDPOINT, requestBody) - req.Header.Set("Content-Type", "application/json") - resp, _ := http.DefaultClient.Do(req) - - defer resp.Body.Close() - - // decode response into a map to extract result - err := json.NewDecoder(resp.Body).Decode(&RlpResp) - PanicIfError(err) - - return RlpResp -} - -func GetPayload(method string, blockNumHash string) *bytes.Reader { - data := PayloadBlock{ - Method: method, - Params: []any{blockNumHash}, - ID: 1, - Jsonrpc: "2.0", - } - payloadBytes, _ := json.Marshal(data) - payload := bytes.NewReader(payloadBytes) - return payload -} - -func HexStrToBytes(hexStr string) []byte { - hexStr = hexStr[2:] - resBytes := common.FromHex(hexStr) - - return resBytes -} - -/* -Iterate over a sequence of block numbers and retrieve the RLP-encoded header for each block. -*/ -func HeaderThroughput() { - numBlocks := len(BlockNums) - startTime := time.Now() - - for i := 0; i < numBlocks; i++ { - payload := GetPayload("debug_getRawHeader", BlockNums[i]) - headerRlp := ExecuteRequest(payload) - headerBytes := StringToBytes(headerRlp["result"].(string)) - - if len(headerBytes) == 0 { - fmt.Println("header bytes is empty") - } - } - - endTime := time.Now() - throughput := float64(numBlocks) / float64(endTime.Sub(startTime).Milliseconds()) * 1000 - fmt.Println("header throughput: ", throughput) -} - -/* -Iterate over a sequence of block numbers and retrieve the RLP-encoded blocks -*/ -func BlockThroughput() { - numBlocks := len(BlockNums) - startTime := time.Now() - - for i := 0; i < numBlocks; i++ { - payload := GetPayload("debug_getRawBlock", BlockNums[i]) - blockRlp := ExecuteRequest(payload) - blockBytes := StringToBytes(blockRlp["result"].(string)) - - EthBlock = new(types.Block) - if err := rlp.Decode(bytes.NewReader(blockBytes), &EthBlock); err != nil { - PanicIfError(err) - } - - // check if block hash matches - if EthBlock.Hash() != EthBlock.Header().Hash() { - fmt.Errorf("block hash does not match header hash") - } - } - - endTime := time.Now() - throughput := float64(numBlocks) / float64(endTime.Sub(startTime).Milliseconds()) * 1000 - fmt.Println("block throughput: ", throughput) -} - -func HeaderBloomThroughput() { - eventSigHash := crypto.Keccak256([]byte("SyncMsg(bytes16,bytes32)")) - sessionId := common.Hex2Bytes("52fdfc072182654f163f5f0f9a621d7200000000000000000000000000000000") - nonce := common.Hex2Bytes("9566c74d10037c4d7bbb0407d1e2c64981855ad8681d0d86d1e91e00167939cb") - - numBlocks := len(BlockNums) - startTime := time.Now() - - for i := 0; i < numBlocks; i++ { - payload := GetPayload("debug_getRawHeader", BlockNums[i]) - headerRlp := ExecuteRequest(payload) - headerBytes := StringToBytes(headerRlp["result"].(string)) - - EthHeader = new(types.Header) - if err := rlp.Decode(bytes.NewReader(headerBytes), &EthHeader); err != nil { - PanicIfError(err) - } - - // check if event signature, sessionId, and nonce are in the header bloom - headerBloom := EthHeader.Bloom.Bytes() - if CheckBloomBits(headerBloom, eventSigHash, sessionId, nonce) { - fmt.Println("event found in header bloom") - } - } - - endTime := time.Now() - throughput := float64(numBlocks) / float64(endTime.Sub(startTime).Milliseconds()) * 1000 - fmt.Println("header bloom throughput: ", throughput) -} - -func CheckReceipt(receipt *types.Receipt, eventDetails [3][]byte) bool { - if len(receipt.Logs) > 0 { - topics := receipt.Logs[0].Topics - if len(topics) == len(eventDetails) { - match := true - for j := 0; j < len(eventDetails); j++ { - if !bytes.Equal(eventDetails[j], topics[j].Bytes()) { - return false - } - } - if match { - fmt.Println("event sig: ", topics[0].Hex()) - return true - } - } - } - return false -} - -func EventInReceipts(receiptsRlp []interface{}, eventDetails [3][]byte) bool { - eventFound := false - numReceipts := len(receiptsRlp) - for i := 0; i < numReceipts; i++ { - receipt := new(types.Receipt) - receiptStr := receiptsRlp[i].(string) - receiptsBytes := HexStrToBytes(receiptStr) - - if err := receipt.UnmarshalBinary(receiptsBytes); err != nil { - PanicIfError(err) - } - - if CheckReceipt(receipt, eventDetails) { - eventFound = true - break - } - } - return eventFound -} - -func BloomAndReceiptThroughput() { - eventSigHash := crypto.Keccak256([]byte("SyncMsg(bytes16,bytes32)")) - sessionId := common.Hex2Bytes("52fdfc072182654f163f5f0f9a621d7200000000000000000000000000000000") - nonce := common.Hex2Bytes("9566c74d10037c4d7bbb0407d1e2c64981855ad8681d0d86d1e91e00167939cb") - eventDetails := [3][]byte{eventSigHash, sessionId, nonce} - - numBlocks := len(BlockNums) - startTime := time.Now() - - for i := 0; i < numBlocks; i++ { - requestPayload := GetPayload("debug_getRawHeader", BlockNums[i]) - headerRlp := ExecuteRequest(requestPayload) - headerBytes := StringToBytes(headerRlp["result"].(string)) - - if err := rlp.Decode(bytes.NewReader(headerBytes), &EthHeader); err != nil { - PanicIfError(err) - } - // check if event signature, sessionId, and nonce are in the header bloom - headerBloom := EthHeader.Bloom.Bytes() - if CheckBloomBits(headerBloom, eventSigHash, sessionId, nonce) { - requestPayload := GetPayload("debug_getRawReceipts", BlockNums[i]) - resultsRlp := ExecuteRequest(requestPayload) - receiptsRlp := resultsRlp["result"].([]interface{}) - - eventFound := EventInReceipts(receiptsRlp, eventDetails) - if eventFound { - fmt.Println("found event in receipt bloom") - } else { - fmt.Println("false positive") - } - } - } - - endTime := time.Now() - throughput := float64(numBlocks) / float64(endTime.Sub(startTime).Milliseconds()) * 1000 - fmt.Println("bloom and receipt throughput: ", throughput) -} - -func main() { - GenerateBlockNums() - - //// Throughput tests - HeaderThroughput() - BlockThroughput() - HeaderBloomThroughput() - BloomAndReceiptThroughput() - - //// Test functions - // ethClient := GetEthClient(LOCAL_ENDPOINT) - // CheckBlockForEvent(big.NewInt(8628615), ethClient) -} - -/** -****************************************************** - Test Functions -****************************************************** -*/ - -func GetEthClient(endpoint string) *ethclient.Client { - client, err := ethclient.Dial(endpoint) - PanicIfError(err) - - return client -} - -func CheckBlockForEvent(blocknum *big.Int, client *ethclient.Client) { - eventSig := []byte("SyncMsg(bytes16,bytes32)") - hash := crypto.Keccak256(eventSig) - eventSigHash := common.BytesToHash(hash) - fmt.Println("eventSigHash: ", hash) - - block, err := client.BlockByNumber(context.Background(), blocknum) - PanicIfError(err) - - contractAddr := "0x74Be867FBD89bC3507F145b36ba76cd0B1bF4f1A" - SyncContractAddr := common.HexToAddress(contractAddr) - - txns := block.Transactions() - numTxns := len(txns) - var txnHash common.Hash - found := false - for i := 0; i < numTxns; i++ { - to := txns[i].To() - if to != nil && *to == SyncContractAddr { - txnHash = txns[i].Hash() - found = true - fmt.Println("sync contract address found") - } - } - - if found { - receipt, err := client.TransactionReceipt(context.Background(), txnHash) - PanicIfError(err) - - logs := receipt.Logs - topics := logs[0].Topics - - if topics[0] == eventSigHash { - fmt.Println("sync event found") - fmt.Println("event parameters: ") - - for i := 1; i < len(topics); i++ { - fmt.Println(topics[i].Bytes()) - } - } - } -} diff --git a/eth_accounts/Start_Ganache.txt b/eth_accounts/Start_Ganache.txt deleted file mode 100644 index 6da3931..0000000 --- a/eth_accounts/Start_Ganache.txt +++ /dev/null @@ -1,10 +0,0 @@ -To start Ganache and make new keys: - -ganache-cli -d -a 20 --network-id 1337 --wallet.accountKeysPath [path_to_decent_lib]/decent-pubsub-onchain/eth_accounts/keys.json - -Start Ganache with keys.json folder existing: -ganache-cli -d -a 20 --network-id 1337 - --d = deterministic (deterministic private keys for testing) - --a 20 = create 20 accounts \ No newline at end of file diff --git a/tests/Makefile b/tests/Makefile index 55fc8dd..1fc8a5c 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -3,6 +3,8 @@ CONTRACTS := \ HelloWorldPublisher \ HelloWorldSubscriber +CHECKSUM_BIN := openssl sha256 + all: $(addprefix ../build/$(MODULE_NAME)/,$(addsuffix .abi,$(CONTRACTS))) \ $(addprefix ../build/$(MODULE_NAME)/,$(addsuffix .bin,$(CONTRACTS))) \ @@ -14,36 +16,38 @@ all: $(addprefix ../build/$(MODULE_NAME)/,$(addsuffix .abi,$(CONTRACTS))) \ ../build/$(MODULE_NAME)/%.bin: %.sol ../build/nodeenv.state - . ../build/nodeenv/bin/activate; \ - solcjs --optimize --optimize-runs 200 \ - --bin \ - --include-path node_modules/ --base-path .. \ - --output-dir ../build/$(MODULE_NAME)/ \ - $< && \ - mv ../build/$(MODULE_NAME)/$(MODULE_NAME)_$(basename $<)_sol_$(basename $<).bin \ - ../build/$(MODULE_NAME)/$(basename $<).bin && \ - rm -f ../build/$(MODULE_NAME)/*_sol_*.bin; \ - deactivate_node + ( \ + . ../build/nodeenv/bin/activate && \ + solcjs --optimize --optimize-runs 200 \ + --bin \ + --include-path node_modules/ --base-path .. \ + --output-dir ../build/$(MODULE_NAME)/ \ + $< && \ + mv ../build/$(MODULE_NAME)/$(MODULE_NAME)_$(basename $<)_sol_$(basename $<).bin \ + ../build/$(MODULE_NAME)/$(basename $<).bin && \ + rm -f ../build/$(MODULE_NAME)/*_sol_*.bin \ + ) ../build/$(MODULE_NAME)/%.abi: %.sol ../build/nodeenv.state - . ../build/nodeenv/bin/activate; \ - solcjs --optimize --optimize-runs 200 \ - --abi \ - --include-path node_modules/ --base-path .. \ - --output-dir ../build/$(MODULE_NAME)/ \ - $< && \ - mv ../build/$(MODULE_NAME)/$(MODULE_NAME)_$(basename $<)_sol_$(basename $<).abi \ - ../build/$(MODULE_NAME)/$(basename $<).abi && \ - rm -f ../build/$(MODULE_NAME)/*_sol_*.abi; \ - deactivate_node + ( \ + . ../build/nodeenv/bin/activate && \ + solcjs --optimize --optimize-runs 200 \ + --abi \ + --include-path node_modules/ --base-path .. \ + --output-dir ../build/$(MODULE_NAME)/ \ + $< && \ + mv ../build/$(MODULE_NAME)/$(MODULE_NAME)_$(basename $<)_sol_$(basename $<).abi \ + ../build/$(MODULE_NAME)/$(basename $<).abi && \ + rm -f ../build/$(MODULE_NAME)/*_sol_*.abi \ + ) ../build/$(MODULE_NAME)/checksums.txt: $(addprefix ../build/$(MODULE_NAME)/,$(addsuffix .abi,$(CONTRACTS))) \ $(addprefix ../build/$(MODULE_NAME)/,$(addsuffix .bin,$(CONTRACTS))) ( \ cd ../build/$(MODULE_NAME); \ - sha256sum $(addsuffix .abi,$(CONTRACTS)) $(addsuffix .bin,$(CONTRACTS)) > checksums.txt; \ + $(CHECKSUM_BIN) $(addsuffix .abi,$(CONTRACTS)) $(addsuffix .bin,$(CONTRACTS)) > checksums.txt; \ ) diff --git a/utils/EthContractHelper.py b/utils/EthContractHelper.py new file mode 100644 index 0000000..5ee87ac --- /dev/null +++ b/utils/EthContractHelper.py @@ -0,0 +1,559 @@ +#!/usr/bin/env python3 +# -*- coding:utf-8 -*- +### +# Copyright (c) 2023 Haofan Zheng +# Use of this source code is governed by an MIT-style +# license that can be found in the LICENSE file or at +# https://opensource.org/licenses/MIT. +### + + +import argparse +import json +import logging +import os +import urllib.request +import web3 + +from eth_account.datastructures import SignedTransaction +from typing import Any, Dict, List, Tuple, Union +from web3 import Web3 # python3 -m pip install web3 +from web3.contract.contract import Contract, ContractConstructor, ContractFunction +from web3.types import TxReceipt + +# check web3 version +if list(map(int, web3.__version__.split('.'))) < [ 6, 2, 0 ]: + raise RuntimeError( + 'web3 version {} is not supported; ' + 'please upgrade to version 6.2.0 or above.'.format(web3.__version__) + ) + + +def LoadBytesFromRelease( + projConf: dict, + release: str, + contract: str +) -> Tuple[str, str]: + + urlAbi = projConf['releaseUrl'].format(version=release, contract=contract + '.abi') + with urllib.request.urlopen(urlAbi) as f: + abiBytes = f.read().decode() + + urlBin = projConf['releaseUrl'].format(version=release, contract=contract + '.bin') + with urllib.request.urlopen(urlBin) as f: + binBytes = f.read().decode() + + return abiBytes, binBytes + + +def LoadBytesFromLocal(projConf: dict, contract: str) -> Tuple[str, str]: + + module = projConf['contractModuleMap'][contract] + + pathAbi = os.path.join(projConf['buildDir'], module, contract + '.abi') + if os.path.isfile(pathAbi) is False: + raise FileNotFoundError( + 'Cannot find locally built contract ABI file at {}; ' + 'please build the contract first.'.format(pathAbi) + ) + + with open(pathAbi, 'r') as f: + abiBytes = f.read() + + pathBin = os.path.join(projConf['buildDir'], module, contract + '.bin') + if os.path.isfile(pathBin) is False: + raise FileNotFoundError( + 'Cannot find locally built contract BIN file at {}; ' + 'please build the contract first.'.format(pathBin) + ) + + with open(pathBin, 'r') as f: + binBytes = f.read() + + return abiBytes, binBytes + + +def LoadContract( + w3: Web3, + projConf: Union[ dict, os.PathLike ], + contractName: str, + release: Union[ None, str ] = None, + address: Union[ None, str ] = None, +) -> Contract: + + if not isinstance(projConf, dict): + with open(projConf, 'r') as f: + projConf = json.load(f) + + if release is None: + # load from local build + abiBytes, binBytes = LoadBytesFromLocal(projConf, contractName) + else: + # load from release + abiBytes, binBytes = LoadBytesFromRelease(projConf, release, contractName) + + if address is None: + # deploy new contract + contract = w3.eth.contract(abi=abiBytes, bytecode=binBytes) + else: + # load existing contract + contract = w3.eth.contract(address=address, abi=abiBytes) + + return contract + + +def _EstimateGas( + executable: Union[ ContractConstructor, ContractFunction ], + value: int, +) -> int: + logger = logging.getLogger(__name__ + '.' + _EstimateGas.__name__) + + gas = executable.estimate_gas({ + 'value': value, + }) + logger.info('Estimated gas: {}'.format(gas)) + # add a little bit flexibility + gas = int(gas * 1.1) + + return gas + + +def _DetermineGas( + executable: Union[ ContractConstructor, ContractFunction ], + gas: Union[ None, int ], + value: int, +) -> int: + logger = logging.getLogger(__name__ + '.' + _DetermineGas.__name__) + + if gas is None: + gas = _EstimateGas(executable, value) + + logger.debug('Gas: {}; Value: {}'.format(gas, value)) + + return gas + + +def _FillMessage( + w3: Web3, + gas: int, + value: int, + privKey: Union[ None, str ], +) -> dict: + + msg = { + 'nonce': w3.eth.get_transaction_count(w3.eth.default_account), + 'chainId': w3.eth.chain_id, + 'gas': gas, + 'value': value, + } + if privKey is not None: + msg['maxFeePerGas'] = int(w3.eth.gas_price * 2) + msg['maxPriorityFeePerGas'] = w3.eth.max_priority_fee + + return msg + + +def _SignTx( + w3: Web3, + tx: dict, + privKey: str, + confirmPrompt: bool +) -> SignedTransaction: + logger = logging.getLogger(__name__ + '.' + _SignTx.__name__) + + maxBaseFee = tx['maxFeePerGas'] + maxPriorityFee = tx['maxPriorityFeePerGas'] + gas = tx['gas'] + value = tx['value'] + + balance = w3.eth.get_balance(w3.eth.default_account) + + maxFee = (maxBaseFee + maxPriorityFee) * gas + maxCost = maxFee + value + if maxCost > balance: + raise RuntimeError( + 'Insufficient balance to pay for the transaction' + '(balance {} wei; max cost: {} wei)'.format( + balance, maxCost + ) + ) + + if confirmPrompt: + baseFee = w3.eth.gas_price + baseFeeGwei = w3.from_wei(baseFee, 'gwei') + fee = baseFee * gas + feeGwei = w3.from_wei(fee, 'gwei') + + maxBaseFeeGwei = w3.from_wei(maxBaseFee, 'gwei') + maxPriorityFeeGwei = w3.from_wei(maxPriorityFee, 'gwei') + maxFeeGwei = w3.from_wei(maxFee, 'gwei') + + valueEther = w3.from_wei(value, 'ether') + + cost = fee + value + costEther = w3.from_wei(cost, 'ether') + maxCostEther = w3.from_wei(maxCost, 'ether') + + balanceEther = w3.from_wei(balance, 'ether') + afterBalanceEther = w3.from_wei(balance - cost, 'ether') + minAfterBalanceEther = w3.from_wei(balance - maxCost, 'ether') + + print('Gas: {}'.format(gas)) + print('gas price: {:.9f} Gwei'.format(baseFeeGwei)) + print('Fee: {:.9f} Gwei'.format(feeGwei)) + print('Max fee / gas: {:.9f} Gwei'.format(maxBaseFeeGwei)) + print('Max prior. fee / gas: {:.9f} Gwei'.format(maxPriorityFeeGwei)) + print('Max fee: {:.9f} Gwei'.format(maxFeeGwei)) + print('Value: {:.18f} Ether'.format(valueEther)) + print() + print('Cost: {:.18f} Ether'.format(costEther)) + print('Max cost: {:.18f} Ether'.format(maxCostEther)) + print() + print('Balance: {:.18f} Ether'.format(balanceEther)) + print('After balance: {:.18f} Ether'.format(afterBalanceEther)) + print('Min. after balance: {:.18f} Ether'.format(minAfterBalanceEther)) + + confirm = input('Confirm transaction? (please type "yes", case insensitive): ') + if confirm.lower() != 'yes': + raise RuntimeError('Transaction cancelled') + + logger.info( + 'Signing transaction with max cost of {} wei'.format(maxCost) + ) + signedTx = w3.eth.account.sign_transaction(tx, privKey) + + return signedTx + + +def _DoTransaction( + w3: Web3, + executable: Union[ ContractConstructor, ContractFunction ], + privKey: Union[ None, str ], + gas: Union[ None, int ], + value: int, + confirmPrompt: bool, +) -> TxReceipt: + logger = logging.getLogger(__name__ + '.' + _DoTransaction.__name__) + + gas = _DetermineGas(executable, gas, value) + msg = _FillMessage(w3, gas, value, privKey) + + if privKey is None: + # no signing needed + txHash = executable.transact(msg) + else: + # need to sign + tx = executable.build_transaction(msg) + signedTx = _SignTx(w3, tx, privKey, confirmPrompt) + txHash = w3.eth.send_raw_transaction(signedTx.rawTransaction) + + receipt = w3.eth.wait_for_transaction_receipt(txHash) + + receiptJson = json.dumps(json.loads(Web3.to_json(receipt)), indent=4) + logger.info('Transaction receipt: {}'.format(receiptJson)) + + return receipt + + +def _FindConstructorAbi( + abiList: List[ dict ], +) -> dict: + for abi in abiList: + if abi['type'] == 'constructor': + return abi + + raise ValueError('No constructor found in ABI') + + +def DeployContract( + w3: Web3, + contract: Contract, + arguments: list, + privKey: Union[str, None] = None, + gas: Union[int, None] = None, + value: int = 0, + confirmPrompt: bool = True, +) -> TxReceipt: + logger = logging.getLogger(__name__ + '.' + DeployContract.__name__) + + constrAbi = _FindConstructorAbi(contract.abi) + isPayable = constrAbi['stateMutability'] == 'payable' + executable = contract.constructor(*arguments) + + receipt = _DoTransaction( + w3=w3, + executable=executable, + privKey=privKey, + gas=gas, + value=value if isPayable else 0, + confirmPrompt=confirmPrompt, + ) + logger.info('Contract deployed at {}'.format(receipt.contractAddress)) + + return receipt + + +def _FindFuncAbi( + abiList: List[ dict ], + funcName: str, +) -> dict: + for abi in abiList: + if ( + (abi['type'] == 'function') and + (abi['name'] == funcName) + ): + return abi + + raise ValueError('Function "{}" not found in ABI'.format(funcName)) + + +def CallContractFunc( + w3: Web3, + contract: Contract, + funcName: str, + arguments: list, + privKey: Union[str, None] = None, + gas: Union[int, None] = None, + value: int = 0, + confirmPrompt: bool = True, +) -> Union[TxReceipt, Any]: + logger = logging.getLogger(__name__ + '.' + CallContractFunc.__name__) + + funcAbi = _FindFuncAbi(contract.abi, funcName) + isViewFunc = funcAbi['stateMutability'] == 'view' + isPayable = funcAbi['stateMutability'] == 'payable' + executable = contract.functions[funcName](*arguments) + + if isViewFunc: + logger.info('Calling view function "{}"'.format(funcName)) + result = executable.call() + logger.info('Type:{}; Result: {}'.format(type(result), result)) + + return result + else: + receipt = _DoTransaction( + w3=w3, + executable=executable, + privKey=privKey, + gas=gas, + value=value if isPayable else 0, + confirmPrompt=confirmPrompt, + ) + + return receipt + + +def ConvertValToWei(val: int, unit: str) -> int: + logger = logging.getLogger(__name__ + '.' + ConvertValToWei.__name__) + + valueToSend = Web3.to_wei(val, unit) + valueToSendEth = Web3.from_wei(valueToSend, 'ether') + if valueToSend > 0: + logger.warning( + 'Value to be sent: {:.18f} ether (or {} wei)'.format( + valueToSendEth, + valueToSend + ) + ) + + return int(valueToSend) + + +def _LoadAccountCredentials( + keyJson: os.PathLike, + index: int +) -> Tuple[str, str]: + with open(keyJson, 'r') as f: + keyJson: Dict[str, Dict[str, str]] = json.load(f) + + if index >= len(keyJson['addresses']): + raise IndexError('Cannot find address at index {}'.format(index)) + + address = [ + a for i, a in enumerate(keyJson['addresses'].keys()) if i == index + ][0] + + for addr, priv in keyJson['private_keys'].items(): + if addr.lower() == address.lower(): + return address, priv + + raise KeyError('Cannot find private key for address {}'.format(address)) + + +def SetupSendingAccount( + w3: Web3, + account: int, + keyJson: Union[ None, os.PathLike ] = None, +) -> Union[ str, None ]: + logger = logging.getLogger(__name__ + '.' + SetupSendingAccount.__name__) + + if keyJson is not None: + addr, privKey = _LoadAccountCredentials(keyJson, account) + w3.eth.default_account = addr + else: + w3.eth.default_account = w3.eth.accounts[0] + privKey = None + + logger.info( + 'The address of the account to be used: {}'.format( + w3.eth.default_account + ) + ) + + return privKey + + +def ChecksumGanacheKeysFile(dest: os.PathLike, src: os.PathLike): + with open(src, 'r') as f: + keysJson: Dict[str, Dict[str, str]] = json.load(f) + + addrs = keysJson['addresses'] + addrs = { + Web3.to_checksum_address(k): Web3.to_checksum_address(v) + for k, v in addrs.items() + } + keysJson['addresses'] = addrs + + privKeys = keysJson['private_keys'] + privKeys = { + Web3.to_checksum_address(k): v for k, v in privKeys.items() + } + keysJson['private_keys'] = privKeys + + with open(dest, 'w') as f: + json.dump(keysJson, f, indent='\t') + + +def main(): + argParser = argparse.ArgumentParser( + description='Deploy contracts to Ethereum blockchain' + ) + argParser.add_argument( + '--config', '-c', type=str, default='project_conf.json', required=False, + help='Path to the project configuration file' + ) + argParser.add_argument( + '--verbose', action='store_true', + help='Verbose logging' + ) + argParser.add_argument( + '--http', type=str, default='http://localhost:7545', required=False, + help='HTTP provider URL' + ) + argParser.add_argument( + '--key-json', type=str, default=None, required=False, + help='Path to keys.json' + ) + argParser.add_argument( + '--account', type=int, default=0, required=False, + help='Index of the account to use' + ) + argParser.add_argument( + '--release', type=str, default=None, required=False, + help='Use prebuilt version from GitHub Release of given git version tag' + '(if not set, local built version will be used)' + ) + argParser.add_argument( + '--contract', type=str, required=True, + help='Contract name' + ) + argParser.add_argument( + '--gas', type=int, default=None, required=False, + help='Gas limit' + ) + argParser.add_argument( + '--value', type=int, default=0, required=False, + help='Value to be sent along with the transaction' + ) + argParser.add_argument( + '--value-unit', type=str, default='wei', required=False, + choices=['ether', 'gwei', 'wei'], + help='Unit of value (ether, gwei, wei)' + ) + argParser.add_argument( + '--no-confirm', action='store_true', + help='Do not ask for confirmation' + ) + + # two operations: deploy and call + argParserSubOp = argParser.add_subparsers( + help='Operation to be performed', + dest='operation', + required=True + ) + + argParserSubOpDeploy = argParserSubOp.add_parser('deploy') + argParserSubOpDeploy.add_argument( + '--args', type=str, nargs='*', default=[], required=False, + help='Constructor/function arguments' + ) + + argParserSubOpCall = argParserSubOp.add_parser('call') + argParserSubOpCall.add_argument( + '--address', type=str, default=None, required=True, + help='Address of the contract to be called' + ) + argParserSubOpCall.add_argument( + '--function', type=str, required=True, + help='Call function' + ) + argParserSubOpCall.add_argument( + '--args', type=str, nargs='*', default=[], required=False, + help='Constructor/function arguments' + ) + + args = argParser.parse_args() + + address = None if args.operation != 'call' else args.address + + # logging configuration + loggingFormat = '%(asctime)s %(levelname)s %(message)s' + if args.verbose: + logging.basicConfig(level=logging.DEBUG, format=loggingFormat) + else: + logging.basicConfig(level=logging.INFO, format=loggingFormat) + logger = logging.getLogger(__name__ + main.__name__) + + # connect to Ethereum node + w3 = Web3(Web3.HTTPProvider(args.http)) + if not w3.is_connected(): + raise RuntimeError( + 'Failed to connect to Ethereum node at %s' % args.http + ) + + valueToSend = ConvertValToWei(args.value, args.value_unit) + privKey = SetupSendingAccount(w3, args.account, args.key_json) + contract = LoadContract( + w3=w3, + projConf=args.config, + contractName=args.contract, + release=args.release, + address=address + ) + + # deploy or call contract + if args.operation == 'deploy': + DeployContract( + w3=w3, + contract=contract, + arguments=args.args, + privKey=privKey, + gas=args.gas, + value=valueToSend, + confirmPrompt=(not args.no_confirm) + ) + elif args.operation == 'call': + CallContractFunc( + w3=w3, + contract=contract, + funcName=args.function, + arguments=args.args, + privKey=privKey, + gas=args.gas, + value=valueToSend, + confirmPrompt=(not args.no_confirm) + ) + + +if __name__ == '__main__': + main() diff --git a/utils/GanachePubSubTests.md b/utils/GanachePubSubTests.md new file mode 100644 index 0000000..245ade1 --- /dev/null +++ b/utils/GanachePubSubTests.md @@ -0,0 +1,33 @@ +# PubSub service test with Ganache + +The testing script, [`GanachePubSubTests.py`](./GanachePubSubTests.py), will +start a ganache server as a subprocess +(so you don't need to run ganache separately), +connect to ganache, and run the following tests. + +## Test Coverage + +1. **Deploy** `PubSubService` contract +2. **Deploy** `HelloWorldPublisher` contract +3. **Register** `HelloWorldPublisher` with `PubSubService` +4. **Deploy** `HelloWorldSubscriber` contract +5. `HelloWorldSubscriber` **subscribes** to `HelloWorldPublisher` +6. Generate a random message, and **set** the message to be sent in + `HelloWorldPublisher` +7. `HelloWorldPublisher` **publishes** the message +8. **Get** received message from `HelloWorldSubscriber` and make sure it matches + the message generated in step 6 + +## Requirement + +- Python 3 +- Web3.py >= 6.2.0 +- Ganache +- Nodeenv + +## Run the test + +1. Follow the instruction in [README.md](../README.md#build-locally) + to build the contract locally +2. Under project's root directory, run command + `python3 utils/GanachePubSubTests.py ` diff --git a/utils/GanachePubSubTests.py b/utils/GanachePubSubTests.py new file mode 100644 index 0000000..b6c45d0 --- /dev/null +++ b/utils/GanachePubSubTests.py @@ -0,0 +1,261 @@ +#!/usr/bin/env python3 +# -*- coding:utf-8 -*- +### +# Copyright (c) 2023 Haofan Zheng +# Use of this source code is governed by an MIT-style +# license that can be found in the LICENSE file or at +# https://opensource.org/licenses/MIT. +### + + +import EthContractHelper +import os +import random +import subprocess +import time + +from web3 import Web3 + + +PROJECT_CONFIG_PATH = os.path.join(os.path.dirname(__file__), 'project_conf.json') +CHECKSUM_KEYS_PATH = os.path.join(os.path.dirname(__file__), 'ganache_keys_checksum.json') +GANACHE_KEYS_PATH = os.path.join(os.path.dirname(__file__), 'ganache_keys.json') +GANACHE_PORT = 7545 + + +def StartGanache() -> subprocess.Popen: + cmd = [ + 'ganache-cli', + '-p', str(GANACHE_PORT), + '-d', + '-a', '20', + '--network-id', '1337', + '--wallet.accountKeysPath', GANACHE_KEYS_PATH, + ] + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + return proc + + +def RunTests() -> None: + # connect to ganache + ganacheUrl = 'http://localhost:{}'.format(GANACHE_PORT) + w3 = Web3(Web3.HTTPProvider(ganacheUrl)) + while not w3.is_connected(): + print('Attempting to connect to ganache...') + time.sleep(1) + print('Connected to ganache') + + # setup account + privKey = EthContractHelper.SetupSendingAccount( + w3=w3, + account=0, # use account 0 + keyJson=CHECKSUM_KEYS_PATH + ) + + # deploy PubSub contract + print('Deploying PubSub contract...') + pubSubContract = EthContractHelper.LoadContract( + w3=w3, + projConf=PROJECT_CONFIG_PATH, + contractName='PubSubService', + release=None, # use locally built contract + address=None, # deploy new contract + ) + pubSubReceipt = EthContractHelper.DeployContract( + w3=w3, + contract=pubSubContract, + arguments=[ ], + privKey=privKey, + gas=None, # let web3 estimate + value=0, + confirmPrompt=False # don't prompt for confirmation + ) + pubSubAddr = pubSubReceipt.contractAddress + print('PubSub contract deployed at {}'.format(pubSubAddr)) + + # load deployed PubSub contract + pubSubContract = EthContractHelper.LoadContract( + w3=w3, + projConf=PROJECT_CONFIG_PATH, + contractName='PubSubService', + release=None, # use locally built contract + address=pubSubAddr, # use deployed contract + ) + + # deploy Publisher contract + print('Deploying publisher contract...') + publisherContract = EthContractHelper.LoadContract( + w3=w3, + projConf=PROJECT_CONFIG_PATH, + contractName='HelloWorldPublisher', + release=None, # use locally built contract + address=None, # deploy new contract + ) + publisherReceipt = EthContractHelper.DeployContract( + w3=w3, + contract=publisherContract, + arguments=[ ], + privKey=privKey, + gas=None, # let web3 estimate + value=0, + confirmPrompt=False # don't prompt for confirmation + ) + publisherAddr = publisherReceipt.contractAddress + print('Publisher contract deployed at {}'.format(publisherAddr)) + + # load deployed Publisher contract + publisherContract = EthContractHelper.LoadContract( + w3=w3, + projConf=PROJECT_CONFIG_PATH, + contractName='HelloWorldPublisher', + release=None, # use locally built contract + address=publisherAddr, # use deployed contract + ) + + # register publisher + print('Registering publisher...') + EthContractHelper.CallContractFunc( + w3=w3, + contract=publisherContract, + funcName='register', + arguments=[ pubSubAddr ], + privKey=privKey, + gas=None, # let web3 estimate + value=0, + confirmPrompt=False # don't prompt for confirmation + ) + + # get event manager address + eventMgrAddr = EthContractHelper.CallContractFunc( + w3=w3, + contract=publisherContract, + funcName='m_eventMgrAddr', + arguments=[ ], + privKey=None, + gas=None, + value=0, + confirmPrompt=False # don't prompt for confirmation + ) + print('Event manager address: {}'.format(eventMgrAddr)) + + # deploy Subscriber contract + print('Deploying subscriber contract...') + subscriberContract = EthContractHelper.LoadContract( + w3=w3, + projConf=PROJECT_CONFIG_PATH, + contractName='HelloWorldSubscriber', + release=None, # use locally built contract + address=None, # deploy new contract + ) + subscriberReceipt = EthContractHelper.DeployContract( + w3=w3, + contract=subscriberContract, + arguments=[ pubSubAddr ], + privKey=privKey, + gas=None, # let web3 estimate + value=0, + confirmPrompt=False # don't prompt for confirmation + ) + subscriberAddr = subscriberReceipt.contractAddress + + # load deployed Subscriber contract + subscriberContract = EthContractHelper.LoadContract( + w3=w3, + projConf=PROJECT_CONFIG_PATH, + contractName='HelloWorldSubscriber', + release=None, # use locally built contract + address=subscriberAddr, # use deployed contract + ) + + # subscribe + print('Subscribing...') + EthContractHelper.CallContractFunc( + w3=w3, + contract=subscriberContract, + funcName='subscribe', + arguments=[ publisherAddr ], + privKey=privKey, + gas=None, # let web3 estimate + value=1000000000000000000, # 1 ether + confirmPrompt=False # don't prompt for confirmation + ) + + # generate a random message to be published + expectedMsg = random.randbytes(32).hex() + + # set message to be published + print('Setting message to be published...') + EthContractHelper.CallContractFunc( + w3=w3, + contract=publisherContract, + funcName='setSendData', + arguments=[ expectedMsg ], + privKey=privKey, + gas=None, # let web3 estimate + value=0, + confirmPrompt=False # don't prompt for confirmation + ) + print('Message set to "{}"'.format(expectedMsg)) + + # estimate the gas limit for publishing + numOfSubscribers = 1 + publishEstGas = ( + 90000 + # gas cost before publishing + (numOfSubscribers * 202000) + # gas cost for publishing + 90000 # gas cost after publishing + ) + + # publish + print('Publishing...') + EthContractHelper.CallContractFunc( + w3=w3, + contract=publisherContract, + funcName='publish', + arguments=[ ], + privKey=privKey, + gas=publishEstGas, + value=0, + confirmPrompt=False # don't prompt for confirmation + ) + + # get the message received by the subscriber + msg = EthContractHelper.CallContractFunc( + w3=w3, + contract=subscriberContract, + funcName='m_recvData', + arguments=[ ], + privKey=None, + gas=None, + value=0, + confirmPrompt=False # don't prompt for confirmation + ) + print('Message received: "{}"'.format(msg)) + if msg != expectedMsg: + raise RuntimeError( + 'Message received does not match the expected message "{}"'.format( + expectedMsg + ) + ) + + +def main(): + ganacheProc = StartGanache() + + try: + RunTests() + finally: + # finish and exit + print('Shutting down ganache (it may take ~15 seconds)...') + ganacheProc.terminate() + while ganacheProc.poll() is None: + try: + print('Still waiting for ganache to shut down...') + ganacheProc.wait(timeout=2) + except subprocess.TimeoutExpired: + continue + print('Ganache has been shut down') + + +if __name__ == '__main__': + main() diff --git a/eth_accounts/keys.json b/utils/ganache_keys.json similarity index 100% rename from eth_accounts/keys.json rename to utils/ganache_keys.json diff --git a/utils/ganache_keys_checksum.json b/utils/ganache_keys_checksum.json new file mode 100644 index 0000000..bd88a71 --- /dev/null +++ b/utils/ganache_keys_checksum.json @@ -0,0 +1,46 @@ +{ + "addresses": { + "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1": "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1", + "0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0": "0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0", + "0x22d491Bde2303f2f43325b2108D26f1eAbA1e32b": "0x22d491Bde2303f2f43325b2108D26f1eAbA1e32b", + "0xE11BA2b4D45Eaed5996Cd0823791E0C93114882d": "0xE11BA2b4D45Eaed5996Cd0823791E0C93114882d", + "0xd03ea8624C8C5987235048901fB614fDcA89b117": "0xd03ea8624C8C5987235048901fB614fDcA89b117", + "0x95cED938F7991cd0dFcb48F0a06a40FA1aF46EBC": "0x95cED938F7991cd0dFcb48F0a06a40FA1aF46EBC", + "0x3E5e9111Ae8eB78Fe1CC3bb8915d5D461F3Ef9A9": "0x3E5e9111Ae8eB78Fe1CC3bb8915d5D461F3Ef9A9", + "0x28a8746e75304c0780E011BEd21C72cD78cd535E": "0x28a8746e75304c0780E011BEd21C72cD78cd535E", + "0xACa94ef8bD5ffEE41947b4585a84BdA5a3d3DA6E": "0xACa94ef8bD5ffEE41947b4585a84BdA5a3d3DA6E", + "0x1dF62f291b2E969fB0849d99D9Ce41e2F137006e": "0x1dF62f291b2E969fB0849d99D9Ce41e2F137006e", + "0x610Bb1573d1046FCb8A70Bbbd395754cD57C2b60": "0x610Bb1573d1046FCb8A70Bbbd395754cD57C2b60", + "0x855FA758c77D68a04990E992aA4dcdeF899F654A": "0x855FA758c77D68a04990E992aA4dcdeF899F654A", + "0xfA2435Eacf10Ca62ae6787ba2fB044f8733Ee843": "0xfA2435Eacf10Ca62ae6787ba2fB044f8733Ee843", + "0x64E078A8Aa15A41B85890265648e965De686bAE6": "0x64E078A8Aa15A41B85890265648e965De686bAE6", + "0x2F560290FEF1B3Ada194b6aA9c40aa71f8e95598": "0x2F560290FEF1B3Ada194b6aA9c40aa71f8e95598", + "0xf408f04F9b7691f7174FA2bb73ad6d45fD5d3CBe": "0xf408f04F9b7691f7174FA2bb73ad6d45fD5d3CBe", + "0x66FC63C2572bF3ADD0Fe5d44b97c2E614E35e9a3": "0x66FC63C2572bF3ADD0Fe5d44b97c2E614E35e9a3", + "0xF0D5BC18421fa04D0a2A2ef540ba5A9f04014BE3": "0xF0D5BC18421fa04D0a2A2ef540ba5A9f04014BE3", + "0x325A621DeA613BCFb5B1A69a7aCED0ea4AfBD73A": "0x325A621DeA613BCFb5B1A69a7aCED0ea4AfBD73A", + "0x3fD652C93dFA333979ad762Cf581Df89BaBa6795": "0x3fD652C93dFA333979ad762Cf581Df89BaBa6795" + }, + "private_keys": { + "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1": "0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d", + "0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0": "0x6cbed15c793ce57650b9877cf6fa156fbef513c4e6134f022a85b1ffdd59b2a1", + "0x22d491Bde2303f2f43325b2108D26f1eAbA1e32b": "0x6370fd033278c143179d81c5526140625662b8daa446c22ee2d73db3707e620c", + "0xE11BA2b4D45Eaed5996Cd0823791E0C93114882d": "0x646f1ce2fdad0e6deeeb5c7e8e5543bdde65e86029e2fd9fc169899c440a7913", + "0xd03ea8624C8C5987235048901fB614fDcA89b117": "0xadd53f9a7e588d003326d1cbf9e4a43c061aadd9bc938c843a79e7b4fd2ad743", + "0x95cED938F7991cd0dFcb48F0a06a40FA1aF46EBC": "0x395df67f0c2d2d9fe1ad08d1bc8b6627011959b79c53d7dd6a3536a33ab8a4fd", + "0x3E5e9111Ae8eB78Fe1CC3bb8915d5D461F3Ef9A9": "0xe485d098507f54e7733a205420dfddbe58db035fa577fc294ebd14db90767a52", + "0x28a8746e75304c0780E011BEd21C72cD78cd535E": "0xa453611d9419d0e56f499079478fd72c37b251a94bfde4d19872c44cf65386e3", + "0xACa94ef8bD5ffEE41947b4585a84BdA5a3d3DA6E": "0x829e924fdf021ba3dbbc4225edfece9aca04b929d6e75613329ca6f1d31c0bb4", + "0x1dF62f291b2E969fB0849d99D9Ce41e2F137006e": "0xb0057716d5917badaf911b193b12b910811c1497b5bada8d7711f758981c3773", + "0x610Bb1573d1046FCb8A70Bbbd395754cD57C2b60": "0x77c5495fbb039eed474fc940f29955ed0531693cc9212911efd35dff0373153f", + "0x855FA758c77D68a04990E992aA4dcdeF899F654A": "0xd99b5b29e6da2528bf458b26237a6cf8655a3e3276c1cdc0de1f98cefee81c01", + "0xfA2435Eacf10Ca62ae6787ba2fB044f8733Ee843": "0x9b9c613a36396172eab2d34d72331c8ca83a358781883a535d2941f66db07b24", + "0x64E078A8Aa15A41B85890265648e965De686bAE6": "0x0874049f95d55fb76916262dc70571701b5c4cc5900c0691af75f1a8a52c8268", + "0x2F560290FEF1B3Ada194b6aA9c40aa71f8e95598": "0x21d7212f3b4e5332fd465877b64926e3532653e2798a11255a46f533852dfe46", + "0xf408f04F9b7691f7174FA2bb73ad6d45fD5d3CBe": "0x47b65307d0d654fd4f786b908c04af8fface7710fc998b37d219de19c39ee58c", + "0x66FC63C2572bF3ADD0Fe5d44b97c2E614E35e9a3": "0x66109972a14d82dbdb6894e61f74708f26128814b3359b64f8b66565679f7299", + "0xF0D5BC18421fa04D0a2A2ef540ba5A9f04014BE3": "0x2eac15546def97adc6d69ca6e28eec831189baa2533e7910755d15403a0749e8", + "0x325A621DeA613BCFb5B1A69a7aCED0ea4AfBD73A": "0x2e114163041d2fb8d45f9251db259a68ee6bdbfd6d10fe1ae87c5c4bcd6ba491", + "0x3fD652C93dFA333979ad762Cf581Df89BaBa6795": "0xae9a2e131e9b359b198fa280de53ddbe2247730b881faae7af08e567e58915bd" + } +} \ No newline at end of file diff --git a/utils/ganache_usage.md b/utils/ganache_usage.md new file mode 100644 index 0000000..b1202f9 --- /dev/null +++ b/utils/ganache_usage.md @@ -0,0 +1,17 @@ +# Ganache + +## To start Ganache, create new keys, and add keys to keys directory: +``` +ganache-cli -a 20 --network-id 1337 --wallet.accountKeysPath [path_to_decent_lib]/decent-pubsub-onchain/utils/ganache_keys.json +``` + +## Start Ganache with existing keys.json folder existing: +``` +ganache-cli -d -a 20 --network-id 1337 +``` + +## Notes +``` +-d = deterministic (deterministic private keys for testing) +-a 20 = create 20 accounts +``` diff --git a/utils/project_conf.json b/utils/project_conf.json new file mode 100644 index 0000000..ff720d0 --- /dev/null +++ b/utils/project_conf.json @@ -0,0 +1,10 @@ +{ + "contractModuleMap": { + "PubSubService" : "PubSub", + "EventManager" : "PubSub", + "HelloWorldPublisher" : "tests", + "HelloWorldSubscriber": "tests" + }, + "releaseUrl": "https://github.com/lsd-ucsc/decent-pubsub-onchain/releases/download/{version}/{contract}", + "buildDir" : "build" +}