├── .gitignore ├── .env ├── .gitmodules ├── .gitattributes ├── docker ├── Dockerfile.neo-go-with-tools └── Dockerfile.neo-node-with-plugins ├── config ├── storagedumper.config-client1.json ├── storagedumper.config-client2.json ├── storagedumper.config-consensus.json ├── applicationlogs.config-client1.json ├── applicationlogs.config-client2.json ├── applicationlogs.config-consensus.json ├── dbft.config-consensus.json ├── stateservice.config-client1.json ├── stateservice.config-client2.json ├── stateservice.config-consensus.json ├── tokentracker.config-client1.json ├── tokentracker.config-client2.json ├── tokentracker.config-consensus.json ├── oracle.config-consensus.json ├── oracle.config-client1.json ├── oracle.config-client2.json ├── wallet-client1.privatenet3.json ├── wallet-client2.privatenet3.json ├── rpcserver.config-client1.json ├── rpcserver.config-client2.json ├── rpcserver.config-consensus.json ├── config-client1.privatenet3.json ├── config-client2.privatenet3.json ├── config-consensus.privatenet3.json └── wallet-consensus.privatenet3.json ├── .github ├── actions │ └── load-env │ │ └── action.yml └── workflows │ └── build.yml ├── .devcontainer └── devcontainer.json ├── scripts └── wait_and_invoke.sh ├── http └── client.http ├── docker-compose.yml ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | neo-node/neo 3 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | IMAGE_TAG=neo-node-3.8.2 2 | NEO_GO_VERSION=0.109.0 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "neo"] 2 | path = neo 3 | url = https://github.com/neo-project/neo 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Declare files that will always have LF line endings on checkout. 2 | wait_and_invoke.sh text eol=lf -------------------------------------------------------------------------------- /docker/Dockerfile.neo-go-with-tools: -------------------------------------------------------------------------------- 1 | ARG NEO_GO_VERSION=latest 2 | 3 | FROM nspccdev/neo-go:${NEO_GO_VERSION} 4 | 5 | RUN apk update && apk add curl netcat-openbsd jq 6 | 7 | -------------------------------------------------------------------------------- /config/storagedumper.config-client1.json: -------------------------------------------------------------------------------- 1 | { 2 | "PluginConfiguration": { 3 | "BlockCacheSize": 1000, 4 | "HeightToBegin": 0, 5 | "Exclude": [ -4 ] 6 | } 7 | } -------------------------------------------------------------------------------- /config/storagedumper.config-client2.json: -------------------------------------------------------------------------------- 1 | { 2 | "PluginConfiguration": { 3 | "BlockCacheSize": 1000, 4 | "HeightToBegin": 0, 5 | "Exclude": [ -4 ] 6 | } 7 | } -------------------------------------------------------------------------------- /config/storagedumper.config-consensus.json: -------------------------------------------------------------------------------- 1 | { 2 | "PluginConfiguration": { 3 | "BlockCacheSize": 1000, 4 | "HeightToBegin": 0, 5 | "Exclude": [ -4 ] 6 | } 7 | } -------------------------------------------------------------------------------- /config/applicationlogs.config-client1.json: -------------------------------------------------------------------------------- 1 | { 2 | "PluginConfiguration": { 3 | "Path": "ApplicationLogs_{0}", 4 | "Network": 5195086, 5 | "MaxStackSize": 65535, 6 | "Debug": false 7 | }, 8 | "Dependency": [ 9 | "RpcServer" 10 | ] 11 | } -------------------------------------------------------------------------------- /config/applicationlogs.config-client2.json: -------------------------------------------------------------------------------- 1 | { 2 | "PluginConfiguration": { 3 | "Path": "ApplicationLogs_{0}", 4 | "Network": 5195086, 5 | "MaxStackSize": 65535, 6 | "Debug": false 7 | }, 8 | "Dependency": [ 9 | "RpcServer" 10 | ] 11 | } -------------------------------------------------------------------------------- /config/applicationlogs.config-consensus.json: -------------------------------------------------------------------------------- 1 | { 2 | "PluginConfiguration": { 3 | "Path": "ApplicationLogs_{0}", 4 | "Network": 5195086, 5 | "MaxStackSize": 65535, 6 | "Debug": false 7 | }, 8 | "Dependency": [ 9 | "RpcServer" 10 | ] 11 | } -------------------------------------------------------------------------------- /config/dbft.config-consensus.json: -------------------------------------------------------------------------------- 1 | { 2 | "PluginConfiguration": { 3 | "RecoveryLogs": "ConsensusState", 4 | "IgnoreRecoveryLogs": false, 5 | "AutoStart": true, 6 | "Network": 5195086, 7 | "MaxBlockSize": 2102400, 8 | "MaxBlockSystemFee": 900000000000 9 | } 10 | } -------------------------------------------------------------------------------- /config/stateservice.config-client1.json: -------------------------------------------------------------------------------- 1 | { 2 | "PluginConfiguration": { 3 | "Path": "Data_MPT_{0}", 4 | "FullState": false, 5 | "Network": 5195086, 6 | "AutoVerify": false, 7 | "MaxFindResultItems": 100 8 | }, 9 | "Dependency": [ 10 | "RpcServer" 11 | ] 12 | } -------------------------------------------------------------------------------- /config/stateservice.config-client2.json: -------------------------------------------------------------------------------- 1 | { 2 | "PluginConfiguration": { 3 | "Path": "Data_MPT_{0}", 4 | "FullState": false, 5 | "Network": 5195086, 6 | "AutoVerify": false, 7 | "MaxFindResultItems": 100 8 | }, 9 | "Dependency": [ 10 | "RpcServer" 11 | ] 12 | } -------------------------------------------------------------------------------- /config/stateservice.config-consensus.json: -------------------------------------------------------------------------------- 1 | { 2 | "PluginConfiguration": { 3 | "Path": "Data_MPT_{0}", 4 | "FullState": false, 5 | "Network": 5195086, 6 | "AutoVerify": false, 7 | "MaxFindResultItems": 100 8 | }, 9 | "Dependency": [ 10 | "RpcServer" 11 | ] 12 | } -------------------------------------------------------------------------------- /config/tokentracker.config-client1.json: -------------------------------------------------------------------------------- 1 | { 2 | "PluginConfiguration": { 3 | "DBPath": "TokenBalanceData", 4 | "TrackHistory": true, 5 | "MaxResults": 1000, 6 | "Network": 5195086, 7 | "EnabledTrackers": [ 8 | "NEP-11", 9 | "NEP-17" 10 | ] 11 | }, 12 | "Dependency": [ 13 | "RpcServer" 14 | ] 15 | } -------------------------------------------------------------------------------- /config/tokentracker.config-client2.json: -------------------------------------------------------------------------------- 1 | { 2 | "PluginConfiguration": { 3 | "DBPath": "TokenBalanceData", 4 | "TrackHistory": true, 5 | "MaxResults": 1000, 6 | "Network": 5195086, 7 | "EnabledTrackers": [ 8 | "NEP-11", 9 | "NEP-17" 10 | ] 11 | }, 12 | "Dependency": [ 13 | "RpcServer" 14 | ] 15 | } -------------------------------------------------------------------------------- /config/tokentracker.config-consensus.json: -------------------------------------------------------------------------------- 1 | { 2 | "PluginConfiguration": { 3 | "DBPath": "TokenBalanceData", 4 | "TrackHistory": true, 5 | "MaxResults": 1000, 6 | "Network": 5195086, 7 | "EnabledTrackers": [ 8 | "NEP-11", 9 | "NEP-17" 10 | ] 11 | }, 12 | "Dependency": [ 13 | "RpcServer" 14 | ] 15 | } -------------------------------------------------------------------------------- /.github/actions/load-env/action.yml: -------------------------------------------------------------------------------- 1 | name: 'Load .env' 2 | description: 'Loads variables from .env file' 3 | 4 | outputs: 5 | image-tag: 6 | description: 'Base image id' 7 | value: ${{ steps.loadenv.outputs.IMAGE_TAG }} 8 | 9 | runs: 10 | using: "composite" 11 | steps: 12 | - name: Load .env 13 | id: loadenv 14 | run: | 15 | set -o allexport; source .env; set +o allexport 16 | echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_OUTPUT 17 | shell: bash -------------------------------------------------------------------------------- /config/oracle.config-consensus.json: -------------------------------------------------------------------------------- 1 | { 2 | "PluginConfiguration": { 3 | "Network": 5195086, 4 | "Nodes": [], 5 | "MaxTaskTimeout": 432000000, 6 | "MaxOracleTimeout": 10000, 7 | "AllowPrivateHost": false, 8 | "AllowedContentTypes": [ "application/json" ], 9 | "Https": { 10 | "Timeout": 5000 11 | }, 12 | "NeoFS": { 13 | "EndPoint": "http://127.0.0.1:8080", 14 | "Timeout": 15000 15 | }, 16 | "AutoStart": false 17 | }, 18 | "Dependency": [ 19 | "RpcServer" 20 | ] 21 | } -------------------------------------------------------------------------------- /config/oracle.config-client1.json: -------------------------------------------------------------------------------- 1 | { 2 | "PluginConfiguration": { 3 | "Network": 5195086, 4 | "Nodes": [ 5 | "http://neo-client2:20332" 6 | ], 7 | "MaxTaskTimeout": 432000000, 8 | "MaxOracleTimeout": 10000, 9 | "AllowPrivateHost": false, 10 | "AllowedContentTypes": [ "application/json" ], 11 | "Https": { 12 | "Timeout": 5000 13 | }, 14 | "NeoFS": { 15 | "EndPoint": "http://127.0.0.1:8080", 16 | "Timeout": 15000 17 | }, 18 | "AutoStart": true 19 | }, 20 | "Dependency": [ 21 | "RpcServer" 22 | ] 23 | } -------------------------------------------------------------------------------- /config/oracle.config-client2.json: -------------------------------------------------------------------------------- 1 | { 2 | "PluginConfiguration": { 3 | "Network": 5195086, 4 | "Nodes": [ 5 | "http://neo-client1:10332" 6 | ], 7 | "MaxTaskTimeout": 432000000, 8 | "MaxOracleTimeout": 10000, 9 | "AllowPrivateHost": false, 10 | "AllowedContentTypes": [ "application/json" ], 11 | "Https": { 12 | "Timeout": 5000 13 | }, 14 | "NeoFS": { 15 | "EndPoint": "http://127.0.0.1:8080", 16 | "Timeout": 15000 17 | }, 18 | "AutoStart": true 19 | }, 20 | "Dependency": [ 21 | "RpcServer" 22 | ] 23 | } -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "neo3-privatenet-docker", 3 | "image": "ghcr.io/axlabs/yaky-images/neo-neow3j", 4 | "postCreateCommand": "echo 'Starting your neo3-privatenet-docker...' && docker-compose up", 5 | "forwardPorts": [ 10332, 20332, 40332 ], 6 | "portsAttributes": { 7 | "40332": { 8 | "label": "neo-consensus", 9 | "onAutoForward": "silent" 10 | }, 11 | "10332": { 12 | "label": "neo-client1", 13 | "onAutoForward": "silent" 14 | }, 15 | "20332": { 16 | "label": "neo-client2", 17 | "onAutoForward": "silent" 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /config/wallet-client1.privatenet3.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": null, 3 | "version": "1.0", 4 | "scrypt": { 5 | "n": 16384, 6 | "r": 8, 7 | "p": 8 8 | }, 9 | "accounts": [ 10 | { 11 | "address": "NV1Q1dTdvzPbThPbSFz7zudTmsmgnCwX6c", 12 | "label": null, 13 | "isDefault": false, 14 | "lock": false, 15 | "key": "6PYWaAbWpf6oeH1VrqtdAGawYMsTfcN1GJyarhUFVEq1siNcRJwMpoo456", 16 | "contract": { 17 | "script": "DCECYHo4uAEKj0AcJd0B3xt0rxgn3Ra4IfwHRR8u9/Atpg9BVuezJw==", 18 | "parameters": [ 19 | { 20 | "name": "signature", 21 | "type": "Signature" 22 | } 23 | ], 24 | "deployed": false 25 | }, 26 | "extra": null 27 | } 28 | ], 29 | "extra": null 30 | } -------------------------------------------------------------------------------- /config/wallet-client2.privatenet3.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": null, 3 | "version": "1.0", 4 | "scrypt": { 5 | "n": 16384, 6 | "r": 8, 7 | "p": 8 8 | }, 9 | "accounts": [ 10 | { 11 | "address": "NhJX9eCbkKtgDrh1S4xMTRaHUGbZ5Be7uU", 12 | "label": null, 13 | "isDefault": false, 14 | "lock": false, 15 | "key": "6PYNfKunYGT5sMMqmpkQLB3KRrgvdE2vTEhpXsjQBLFh9cTbRkWkTkz9Q1", 16 | "contract": { 17 | "script": "DCEDcnnzpQeBclFTQYERbLOO8wRoslB0gn2zTLvGrciHOTJBVuezJw==", 18 | "parameters": [ 19 | { 20 | "name": "signature", 21 | "type": "Signature" 22 | } 23 | ], 24 | "deployed": false 25 | }, 26 | "extra": null 27 | } 28 | ], 29 | "extra": null 30 | } -------------------------------------------------------------------------------- /config/rpcserver.config-client1.json: -------------------------------------------------------------------------------- 1 | { 2 | "PluginConfiguration": { 3 | "Servers": [ 4 | { 5 | "Network": 5195086, 6 | "BindAddress": "0.0.0.0", 7 | "Port": 10332, 8 | "SslCert": "", 9 | "SslCertPassword": "", 10 | "TrustedAuthorities": [], 11 | "RpcUser": "", 12 | "RpcPass": "", 13 | "EnableCors": false, 14 | "AllowOrigins": [], 15 | "KeepAliveTimeout": 60, 16 | "RequestHeadersTimeout": 15, 17 | "MaxGasInvoke": 100000, 18 | "MaxFee": 0.1, 19 | "MaxConcurrentConnections": 40, 20 | "MaxIteratorResultItems": 100, 21 | "MaxRequestBodySize": 5242880, 22 | "MaxStackSize": 65535, 23 | "DisabledMethods": [ ], 24 | "SessionEnabled": true, 25 | "SessionExpirationTime": 60, 26 | "FindStoragePageSize": 50 27 | } 28 | ] 29 | } 30 | } -------------------------------------------------------------------------------- /config/rpcserver.config-client2.json: -------------------------------------------------------------------------------- 1 | { 2 | "PluginConfiguration": { 3 | "Servers": [ 4 | { 5 | "Network": 5195086, 6 | "BindAddress": "0.0.0.0", 7 | "Port": 20332, 8 | "SslCert": "", 9 | "SslCertPassword": "", 10 | "TrustedAuthorities": [], 11 | "RpcUser": "", 12 | "RpcPass": "", 13 | "EnableCors": false, 14 | "AllowOrigins": [], 15 | "KeepAliveTimeout": 60, 16 | "RequestHeadersTimeout": 15, 17 | "MaxGasInvoke": 100000, 18 | "MaxFee": 0.1, 19 | "MaxConcurrentConnections": 40, 20 | "MaxIteratorResultItems": 100, 21 | "MaxRequestBodySize": 5242880, 22 | "MaxStackSize": 65535, 23 | "DisabledMethods": [ ], 24 | "SessionEnabled": true, 25 | "SessionExpirationTime": 60, 26 | "FindStoragePageSize": 50 27 | } 28 | ] 29 | } 30 | } -------------------------------------------------------------------------------- /config/rpcserver.config-consensus.json: -------------------------------------------------------------------------------- 1 | { 2 | "PluginConfiguration": { 3 | "Servers": [ 4 | { 5 | "Network": 5195086, 6 | "BindAddress": "0.0.0.0", 7 | "Port": 40332, 8 | "SslCert": "", 9 | "SslCertPassword": "", 10 | "TrustedAuthorities": [], 11 | "RpcUser": "", 12 | "RpcPass": "", 13 | "EnableCors": false, 14 | "AllowOrigins": [], 15 | "KeepAliveTimeout": 60, 16 | "RequestHeadersTimeout": 15, 17 | "MaxGasInvoke": 100000, 18 | "MaxFee": 0.1, 19 | "MaxConcurrentConnections": 40, 20 | "MaxIteratorResultItems": 100, 21 | "MaxRequestBodySize": 5242880, 22 | "MaxStackSize": 65535, 23 | "DisabledMethods": [ ], 24 | "SessionEnabled": true, 25 | "SessionExpirationTime": 60, 26 | "FindStoragePageSize": 50 27 | } 28 | ] 29 | } 30 | } -------------------------------------------------------------------------------- /config/config-client1.privatenet3.json: -------------------------------------------------------------------------------- 1 | { 2 | "ApplicationConfiguration": { 3 | "Logger": { 4 | "Path": "Logs", 5 | "ConsoleOutput": true, 6 | "Active": true 7 | }, 8 | "Storage": { 9 | "Engine": "LevelDBStore", 10 | "Path": "Data_LevelDB_{0}" 11 | }, 12 | "P2P": { 13 | "Port": 10333, 14 | "MinDesiredConnections": 10, 15 | "MaxConnections": 40, 16 | "MaxConnectionsPerAddress": 3 17 | }, 18 | "UnlockWallet": { 19 | "Path": "wallet.json", 20 | "Password": "neo", 21 | "IsActive": true 22 | }, 23 | "Plugins": { 24 | "DownloadUrl": "https://api.github.com/repos/neo-project/neo-modules/releases" 25 | } 26 | }, 27 | "ProtocolConfiguration": { 28 | "Network": 5195086, 29 | "MillisecondsPerBlock": 15000, 30 | "MaxTransactionsPerBlock": 512, 31 | "MemoryPoolMaxTransactions": 50000, 32 | "MaxTraceableBlocks": 2102400, 33 | "InitialGasDistribution": 5200000000000000, 34 | "ValidatorsCount": 1, 35 | "StandbyCommittee": [ 36 | "033a4d051b04b7fc0230d2b1aaedfd5a84be279a5361a7358db665ad7857787f1b" 37 | ], 38 | "SeedList": [ 39 | "neo-consensus:40333" 40 | ] 41 | } 42 | } -------------------------------------------------------------------------------- /config/config-client2.privatenet3.json: -------------------------------------------------------------------------------- 1 | { 2 | "ApplicationConfiguration": { 3 | "Logger": { 4 | "Path": "Logs", 5 | "ConsoleOutput": true, 6 | "Active": true 7 | }, 8 | "Storage": { 9 | "Engine": "LevelDBStore", 10 | "Path": "Data_LevelDB_{0}" 11 | }, 12 | "P2P": { 13 | "Port": 20333, 14 | "MinDesiredConnections": 10, 15 | "MaxConnections": 40, 16 | "MaxConnectionsPerAddress": 3 17 | }, 18 | "UnlockWallet": { 19 | "Path": "wallet.json", 20 | "Password": "neo", 21 | "IsActive": true 22 | }, 23 | "Plugins": { 24 | "DownloadUrl": "https://api.github.com/repos/neo-project/neo-modules/releases" 25 | } 26 | }, 27 | "ProtocolConfiguration": { 28 | "Network": 5195086, 29 | "MillisecondsPerBlock": 15000, 30 | "MaxTransactionsPerBlock": 512, 31 | "MemoryPoolMaxTransactions": 50000, 32 | "MaxTraceableBlocks": 2102400, 33 | "InitialGasDistribution": 5200000000000000, 34 | "ValidatorsCount": 1, 35 | "StandbyCommittee": [ 36 | "033a4d051b04b7fc0230d2b1aaedfd5a84be279a5361a7358db665ad7857787f1b" 37 | ], 38 | "SeedList": [ 39 | "neo-consensus:40333" 40 | ] 41 | } 42 | } -------------------------------------------------------------------------------- /config/config-consensus.privatenet3.json: -------------------------------------------------------------------------------- 1 | { 2 | "ApplicationConfiguration": { 3 | "Logger": { 4 | "Path": "Logs", 5 | "ConsoleOutput": true, 6 | "Active": true 7 | }, 8 | "Storage": { 9 | "Engine": "LevelDBStore", 10 | "Path": "Data_LevelDB_{0}" 11 | }, 12 | "P2P": { 13 | "Port": 40333, 14 | "MinDesiredConnections": 10, 15 | "MaxConnections": 40, 16 | "MaxConnectionsPerAddress": 3 17 | }, 18 | "UnlockWallet": { 19 | "Path": "wallet.json", 20 | "Password": "neo", 21 | "IsActive": true 22 | }, 23 | "Plugins": { 24 | "DownloadUrl": "https://api.github.com/repos/neo-project/neo-modules/releases" 25 | } 26 | }, 27 | "ProtocolConfiguration": { 28 | "Network": 5195086, 29 | "MillisecondsPerBlock": 15000, 30 | "MaxTransactionsPerBlock": 512, 31 | "MemoryPoolMaxTransactions": 50000, 32 | "MaxTraceableBlocks": 2102400, 33 | "InitialGasDistribution": 5200000000000000, 34 | "ValidatorsCount": 1, 35 | "StandbyCommittee": [ 36 | "033a4d051b04b7fc0230d2b1aaedfd5a84be279a5361a7358db665ad7857787f1b" 37 | ], 38 | "SeedList": [ 39 | "localhost:40333" 40 | ] 41 | } 42 | } -------------------------------------------------------------------------------- /config/wallet-consensus.privatenet3.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": null, 3 | "version": "1.0", 4 | "scrypt": { 5 | "n": 16384, 6 | "r": 8, 7 | "p": 8 8 | }, 9 | "accounts": [ 10 | { 11 | "address": "NM7Aky765FG8NhhwtxjXRx7jEL1cnw7PBP", 12 | "label": null, 13 | "isDefault": false, 14 | "lock": false, 15 | "key": "6PYM7jHL4GmS8Aw2iEFpuaHTCUKjhT4mwVqdoozGU6sUE25BjV4ePXDdLz", 16 | "contract": { 17 | "script": "DCEDOk0FGwS3/AIw0rGq7f1ahL4nmlNhpzWNtmWteFd4fxtBVuezJw==", 18 | "parameters": [ 19 | { 20 | "name": "signature", 21 | "type": "Signature" 22 | } 23 | ], 24 | "deployed": false 25 | }, 26 | "extra": null 27 | }, 28 | { 29 | "address": "NXXazKH39yNFWWZF5MJ8tEN98VYHwzn7g3", 30 | "label": null, 31 | "isDefault": false, 32 | "lock": false, 33 | "key": "6PYM7jHL4GmS8Aw2iEFpuaHTCUKjhT4mwVqdoozGU6sUE25BjV4ePXDdLz", 34 | "contract": { 35 | "script": "EQwhAzpNBRsEt/wCMNKxqu39WoS+J5pTYac1jbZlrXhXeH8bEUGe0Nw6", 36 | "parameters": [ 37 | { 38 | "name": "parameter0", 39 | "type": "Signature" 40 | } 41 | ], 42 | "deployed": false 43 | }, 44 | "extra": null 45 | } 46 | ], 47 | "extra": null 48 | } -------------------------------------------------------------------------------- /docker/Dockerfile.neo-node-with-plugins: -------------------------------------------------------------------------------- 1 | # Build the plugins 2 | FROM mcr.microsoft.com/dotnet/sdk:9.0 AS plugin-build 3 | 4 | COPY ./neo /neo 5 | WORKDIR /neo 6 | 7 | # If any plugin should be excluded from the build, just set 8 | # to a regex including the names of dirs. 9 | # Example: 10 | # REGEX_EXCLUDE_PLUGINS=".*(MPTTrie|RpcClient)" 11 | ARG REGEX_EXCLUDE_PLUGINS=".*(MPTTrie|RpcClient)" 12 | 13 | # Target framework for the plugins 14 | # ATTENTION: if dotnet version changes, this should be updated! 15 | ENV TARGET_FRAMEWORK="net9.0" 16 | 17 | # 18 | # Some magic here. Time for the kids to leave. Adults only. 19 | # 20 | # The following disgusting shell command is due to the lack of tooling 21 | # to exclude tests and specific sub-projects in dotnet. *facepalm* 22 | # 23 | # The good side: main artifacts and tests are not mixed up in the 24 | # same plugins directory, avoiding potential conflicts of .dll versions 25 | # and other nasty problems. *smile* 26 | # 27 | RUN mkdir -p /plugins && \ 28 | find ./src/Plugins \ 29 | -regextype posix-extended \ 30 | -maxdepth 1 \ 31 | -mindepth 1 \ 32 | -type d \ 33 | -and -not -name '.*' \ 34 | -and -not -regex "${REGEX_EXCLUDE_PLUGINS}" -print0 \ 35 | | xargs -0 -L1 sh -c 'basename $0' \ 36 | | sed 's/ //g' \ 37 | | xargs -I {} sh -c 'echo Building {} && dotnet publish ./src/Plugins/{} -f $TARGET_FRAMEWORK -c Release /p:ErrorOnDuplicatePublishOutputFiles=false -o /plugins && mkdir -p /plugins/{} && mv /plugins/{}.* /plugins/{}/' 38 | 39 | # Build the Neo.CLI 40 | FROM mcr.microsoft.com/dotnet/sdk:9.0 AS neo-cli-build 41 | 42 | COPY ./neo /neo 43 | 44 | WORKDIR /neo 45 | RUN dotnet restore && dotnet publish ./src/Neo.CLI -c Release -o /cli 46 | 47 | # Final image: neo-node-with-plugins :-) 48 | FROM mcr.microsoft.com/dotnet/sdk:9.0 AS neo-cli-final 49 | 50 | LABEL org.opencontainers.image.source https://github.com/axlabs/neo3-privatenet-docker 51 | 52 | RUN apt-get -y update && \ 53 | apt-get -y install jq nano procps screen libleveldb-dev sqlite3 expect && \ 54 | rm -rf /var/lib/apt/lists/* 55 | 56 | WORKDIR /neo-cli 57 | 58 | COPY --from=neo-cli-build /cli . 59 | COPY --from=plugin-build /plugins ./Plugins 60 | 61 | ENTRYPOINT ["screen","-DmS","node","dotnet","neo-cli.dll"] -------------------------------------------------------------------------------- /scripts/wait_and_invoke.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | set -e 4 | echo "Starting script..." 5 | 6 | echo "Checking if neo-node is up..." 7 | until nc -z neo-consensus 40332; do 8 | echo "Waiting for neo-node..." 9 | sleep 5 10 | done 11 | echo "Neo-node is up!" 12 | 13 | echo "Creating wallet.config file..." 14 | echo "{ 15 | \"Path\": \"/wallet.json\", 16 | \"Password\": \"${WALLET_PASSWORD}\" 17 | }" > /wallet.config 18 | 19 | echo "Starting block height check..." 20 | TEMPFILE=$(mktemp) 21 | trap "rm -f $TEMPFILE" EXIT 22 | while true; do 23 | echo "Checking block height..." 24 | sleep 5 25 | curl -s -X POST http://neo-consensus:40332 \ 26 | -H "Content-Type: application/json" \ 27 | -d '{"jsonrpc":"2.0","method":"getblockcount","params":[],"id":1}' > $TEMPFILE 28 | RESPONSE=$(cat $TEMPFILE) 29 | echo "Curl response: $RESPONSE" 30 | if [ -z "$RESPONSE" ]; then 31 | echo "Error: No response from curl" 32 | continue 33 | fi 34 | HEIGHT=$(cat $TEMPFILE | jq ".result | tonumber" 2>/dev/null) 35 | echo "Parsed height: $HEIGHT" 36 | if [ -z "$HEIGHT" ] || [ "$HEIGHT" = "null" ]; then 37 | HEIGHT=0 38 | fi 39 | echo "Current block height: $HEIGHT" 40 | if [ "$HEIGHT" -ge 1 ]; then 41 | echo "Block height is $HEIGHT. Proceeding..." 42 | break 43 | fi 44 | done 45 | 46 | echo "Invoking 'RoleManagement' contract, method 'designateAsRole'..." 47 | 48 | neo-go contract invokefunction --await --force -r http://neo-consensus:40332 \ 49 | --wallet-config /wallet.config \ 50 | --address NXXazKH39yNFWWZF5MJ8tEN98VYHwzn7g3 \ 51 | 49cf4e5378ffcd4dec034fd98a174c5491e395e2 \ 52 | designateAsRole int:8 \ 53 | [ key:02607a38b8010a8f401c25dd01df1b74af1827dd16b821fc07451f2ef7f02da60f \ 54 | key:037279f3a507817251534181116cb38ef30468b25074827db34cbbc6adc8873932 ] \ 55 | -- NXXazKH39yNFWWZF5MJ8tEN98VYHwzn7g3:Global 56 | 57 | echo "Funding address NM7Aky765FG8NhhwtxjXRx7jEL1cnw7PBP (neo-consensus, normal wallet) with 10000000 GAS and 10000000 NEO..." 58 | echo "Funding address NV1Q1dTdvzPbThPbSFz7zudTmsmgnCwX6c (neo-client1) with 10000000 GAS and 10000000 NEO..." 59 | echo "Funding address NhJX9eCbkKtgDrh1S4xMTRaHUGbZ5Be7uU (neo-client2) with 10000000 GAS and 10000000 NEO..." 60 | 61 | neo-go wallet nep17 multitransfer --await --force -r http://neo-consensus:40332 \ 62 | --wallet-config /wallet.config \ 63 | --from NXXazKH39yNFWWZF5MJ8tEN98VYHwzn7g3 \ 64 | GAS:NM7Aky765FG8NhhwtxjXRx7jEL1cnw7PBP:10000000 \ 65 | NEO:NM7Aky765FG8NhhwtxjXRx7jEL1cnw7PBP:10000000 \ 66 | NEO:NXXazKH39yNFWWZF5MJ8tEN98VYHwzn7g3:0 \ 67 | GAS:NV1Q1dTdvzPbThPbSFz7zudTmsmgnCwX6c:10000000 \ 68 | NEO:NV1Q1dTdvzPbThPbSFz7zudTmsmgnCwX6c:10000000 \ 69 | GAS:NhJX9eCbkKtgDrh1S4xMTRaHUGbZ5Be7uU:10000000 \ 70 | NEO:NhJX9eCbkKtgDrh1S4xMTRaHUGbZ5Be7uU:10000000 \ 71 | -- NXXazKH39yNFWWZF5MJ8tEN98VYHwzn7g3:Global 72 | -------------------------------------------------------------------------------- /http/client.http: -------------------------------------------------------------------------------- 1 | ### 2 | # Get the latest block index of `neo-consensus` node: 3 | ### 4 | 5 | POST http://127.0.0.1:40332 HTTP/1.1 6 | content-type: application/json 7 | 8 | { 9 | "jsonrpc":"2.0", 10 | "method":"getblockcount", 11 | "params":[], 12 | "id":1 13 | } 14 | 15 | ### 16 | # Open the wallet from the `neo-consensus` node 17 | ### 18 | 19 | POST http://127.0.0.1:40332 HTTP/1.1 20 | content-type: application/json 21 | 22 | { 23 | "jsonrpc":"2.0", 24 | "method":"openwallet", 25 | "params":["wallet.json","neo"], 26 | "id":1 27 | } 28 | 29 | ### 30 | # List the addresses in `neo-consensus` wallet: 31 | ### 32 | 33 | POST http://127.0.0.1:40332 HTTP/1.1 34 | content-type: application/json 35 | 36 | { 37 | "jsonrpc":"2.0", 38 | "method":"listaddress", 39 | "params":[], 40 | "id":1 41 | } 42 | 43 | ### 44 | # Get all NEP-17 balance of `neo-consensus`' 45 | # address `NKvR5WeczCQMcVWQD9aaMqegfEoCBXGWpW`, specifically: 46 | ### 47 | 48 | POST http://127.0.0.1:40332 HTTP/1.1 49 | content-type: application/json 50 | 51 | { 52 | "jsonrpc":"2.0", 53 | "method":"getnep17balances", 54 | "params":["NXXazKH39yNFWWZF5MJ8tEN98VYHwzn7g3"], 55 | "id":1 56 | } 57 | 58 | ### 59 | # Send 100 NEO from `neo-consensus`' address `NXXazKH39yNFWWZF5MJ8tEN98VYHwzn7g3` 60 | # to `neo-client1`'s address `NdihqSLYTf1B1WYuzhM52MNqvCNPJKLZaz` 61 | ### 62 | 63 | POST http://127.0.0.1:40332 HTTP/1.1 64 | content-type: application/json 65 | 66 | { 67 | "jsonrpc":"2.0", 68 | "method":"sendfrom", 69 | "params":[ 70 | "0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5", 71 | "NXXazKH39yNFWWZF5MJ8tEN98VYHwzn7g3", 72 | "NdihqSLYTf1B1WYuzhM52MNqvCNPJKLZaz", 73 | 100 74 | ], 75 | "id":1 76 | } 77 | 78 | ### 79 | # Open the wallet of the `neo-client1` 80 | # through JSON-RPC (**only for test purposes!**): 81 | ### 82 | 83 | POST http://127.0.0.1:10332 HTTP/1.1 84 | content-type: application/json 85 | 86 | { 87 | "jsonrpc":"2.0", 88 | "method":"openwallet", 89 | "params":["wallet.json","neo"], 90 | "id":1 91 | } 92 | 93 | ### 94 | # Get all NEP-17 balance of `neo-client1`' address `NdihqSLYTf1B1WYuzhM52MNqvCNPJKLZaz` 95 | # (wait 15 seconds before executing the command, due to the block generation interval): 96 | ### 97 | 98 | POST http://127.0.0.1:10332 HTTP/1.1 99 | content-type: application/json 100 | 101 | { 102 | "jsonrpc":"2.0", 103 | "method":"getnep17balances", 104 | "params":["NdihqSLYTf1B1WYuzhM52MNqvCNPJKLZaz"], 105 | "id":1 106 | } 107 | 108 | ### 109 | # Gets all public keys that has role 'Oracle' from the Role Management contract 110 | ### 111 | POST http://127.0.0.1:40332 HTTP/1.1 112 | content-type: application/json 113 | 114 | { 115 | "jsonrpc": "2.0", 116 | "id": 1, 117 | "method": "invokefunction", 118 | "params": [ 119 | "0x49cf4e5378ffcd4dec034fd98a174c5491e395e2", 120 | "getDesignatedByRole", 121 | [ 122 | { 123 | "type":"Integer", 124 | "value":8 125 | }, 126 | { 127 | "type":"Integer", 128 | "value":10 129 | } 130 | ], 131 | [ 132 | ], 133 | true 134 | ] 135 | } -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | 3 | services: 4 | 5 | neo-consensus: 6 | build: 7 | context: ./ 8 | dockerfile: ./docker/Dockerfile.neo-node-with-plugins 9 | target: neo-cli-final 10 | args: 11 | IMAGE_TAG: ${IMAGE_TAG} 12 | image: ghcr.io/axlabs/neo3-privatenet-docker/neo-cli-with-plugins:${IMAGE_TAG} 13 | hostname: neo-consensus 14 | container_name: neo-consensus 15 | volumes: 16 | - ./config/config-consensus.privatenet3.json:/neo-cli/config.json:ro 17 | - ./config/wallet-consensus.privatenet3.json:/neo-cli/wallet.json:rw 18 | - ./config/rpcserver.config-consensus.json:/neo-cli/Plugins/RpcServer/RpcServer.json:ro 19 | - ./config/dbft.config-consensus.json:/neo-cli/Plugins/DBFTPlugin/DBFTPlugin.json:ro 20 | - ./config/applicationlogs.config-consensus.json:/neo-cli/Plugins/ApplicationLogs/ApplicationLogs.json:ro 21 | - ./config/oracle.config-consensus.json:/neo-cli/Plugins/OracleService/OracleService.json:ro 22 | - ./config/tokentracker.config-consensus.json:/neo-cli/Plugins/TokensTracker/TokensTracker.json:ro 23 | - ./config/stateservice.config-consensus.json:/neo-cli/Plugins/StateService/StateService.json:ro 24 | - ./config/storagedumper.config-consensus.json:/neo-cli/Plugins/StorageDumper/StorageDumper.json:ro 25 | ports: 26 | - "40332:40332" 27 | 28 | neo-client1: 29 | image: ghcr.io/axlabs/neo3-privatenet-docker/neo-cli-with-plugins:${IMAGE_TAG} 30 | hostname: neo-client1 31 | container_name: neo-client1 32 | depends_on: 33 | - neo-consensus 34 | volumes: 35 | - ./config/config-client1.privatenet3.json:/neo-cli/config.json:ro 36 | - ./config/wallet-client1.privatenet3.json:/neo-cli/wallet.json:rw 37 | - ./config/rpcserver.config-client1.json:/neo-cli/Plugins/RpcServer/RpcServer.json:ro 38 | - ./config/applicationlogs.config-client1.json:/neo-cli/Plugins/ApplicationLogs/ApplicationLogs.json:ro 39 | - ./config/oracle.config-client1.json:/neo-cli/Plugins/OracleService/OracleService.json:ro 40 | - ./config/tokentracker.config-client1.json:/neo-cli/Plugins/TokensTracker/TokensTracker.json:ro 41 | - ./config/stateservice.config-client1.json:/neo-cli/Plugins/StateService/StateService.json:ro 42 | - ./config/storagedumper.config-client1.json:/neo-cli/Plugins/StorageDumper/StorageDumper.json:ro 43 | ports: 44 | - "10332:10332" 45 | 46 | neo-client2: 47 | image: ghcr.io/axlabs/neo3-privatenet-docker/neo-cli-with-plugins:${IMAGE_TAG} 48 | hostname: neo-client2 49 | container_name: neo-client2 50 | depends_on: 51 | - neo-consensus 52 | volumes: 53 | - ./config/config-client2.privatenet3.json:/neo-cli/config.json:ro 54 | - ./config/wallet-client2.privatenet3.json:/neo-cli/wallet.json:rw 55 | - ./config/rpcserver.config-client2.json:/neo-cli/Plugins/RpcServer/RpcServer.json:ro 56 | - ./config/applicationlogs.config-client2.json:/neo-cli/Plugins/ApplicationLogs/ApplicationLogs.json:ro 57 | - ./config/oracle.config-client2.json:/neo-cli/Plugins/OracleService/OracleService.json:ro 58 | - ./config/tokentracker.config-client2.json:/neo-cli/Plugins/TokensTracker/TokensTracker.json:ro 59 | - ./config/stateservice.config-client2.json:/neo-cli/Plugins/StateService/StateService.json:ro 60 | - ./config/storagedumper.config-client2.json:/neo-cli/Plugins/StorageDumper/StorageDumper.json:ro 61 | ports: 62 | - "20332:20332" 63 | 64 | neo-go-cli: 65 | build: 66 | context: ./ 67 | dockerfile: ./docker/Dockerfile.neo-go-with-tools 68 | args: 69 | NEO_GO_VERSION: ${NEO_GO_VERSION} 70 | hostname: neo-go-cli 71 | container_name: neo-go-cli 72 | environment: 73 | - WALLET_PASSWORD=neo 74 | volumes: 75 | - ./config/wallet-consensus.privatenet3.json:/wallet.json:ro 76 | - ./scripts/wait_and_invoke.sh:/wait_and_invoke.sh:ro 77 | entrypoint: ["sh", "/wait_and_invoke.sh"] -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build and Publish container (multi-platform) 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | publish: 7 | description: 'Publish to ghcr?' 8 | required: true 9 | default: 'true' 10 | set-latest-tag: 11 | description: 'Publish tag "latest"?' 12 | required: true 13 | default: 'false' 14 | 15 | env: 16 | IMAGE_ID: ghcr.io/axlabs/neo3-privatenet-docker/neo-cli-with-plugins 17 | VERSION_LATEST: latest 18 | 19 | jobs: 20 | 21 | build: 22 | runs-on: ${{ (matrix.platform == 'linux/amd64' && 'ubuntu-latest') || (matrix.platform == 'linux/arm64' && 'ARM64') }} 23 | strategy: 24 | fail-fast: false 25 | matrix: 26 | platform: 27 | - linux/amd64 28 | - linux/arm64 29 | steps: 30 | - name: Prepare 31 | run: | 32 | platform=${{ matrix.platform }} 33 | echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV 34 | 35 | - name: Checkout 36 | uses: actions/checkout@v4 37 | with: 38 | submodules: recursive 39 | 40 | - name: Set up Docker Buildx 41 | uses: docker/setup-buildx-action@v3 42 | with: 43 | config: buildkit-config.toml 44 | 45 | - name: Login to GitHub Container Registry 46 | uses: docker/login-action@v3 47 | with: 48 | registry: ghcr.io 49 | username: ${{ github.actor }} 50 | password: ${{ secrets.GITHUB_TOKEN }} 51 | 52 | - name: Load .env 53 | id: loadenv 54 | uses: ./.github/actions/load-env 55 | 56 | - name: Build and push neo-cli-with-plugins 57 | id: build-plugins-image 58 | uses: docker/build-push-action@v5 59 | with: 60 | platforms: ${{ matrix.platform }} 61 | file: ./docker/Dockerfile.neo-node-with-plugins 62 | target: neo-cli-final 63 | build-args: IMAGE_TAG=${{ steps.loadenv.outputs.image-tag }} 64 | context: ./ 65 | outputs: type=image,name=${{ env.IMAGE_ID }},push-by-digest=true,name-canonical=true,push=${{ github.event.inputs.publish }} 66 | 67 | - name: Clean up digests dir - neo-cli-with-plugins 68 | run: | 69 | rm -rf /tmp/digests-plugins-image 70 | mkdir -p /tmp/digests-plugins-image 71 | 72 | - name: Export digest - neo-cli-with-plugins 73 | run: | 74 | digest="${{ steps.build-plugins-image.outputs.digest }}" 75 | touch "/tmp/digests-plugins-image/${digest#sha256:}" 76 | 77 | - name: Upload digest - neo-cli-with-plugins 78 | if: github.event.inputs.publish == 'true' 79 | uses: actions/upload-artifact@v4 80 | with: 81 | name: digests-plugins-image-${{ env.PLATFORM_PAIR }} 82 | path: /tmp/digests-plugins-image/* 83 | if-no-files-found: error 84 | retention-days: 1 85 | 86 | merge-docker-manifests: 87 | runs-on: ubuntu-latest 88 | if: github.event.inputs.publish == 'true' 89 | needs: 90 | - build 91 | steps: 92 | - name: Checkout 93 | uses: actions/checkout@v4 94 | 95 | - name: Load .env 96 | id: loadenv 97 | uses: ./.github/actions/load-env 98 | 99 | - name: Clean up digests dir - neo-cli-with-plugins 100 | run: | 101 | rm -rf /tmp/digests-plugins-image 102 | mkdir -p /tmp/digests-plugins-image 103 | 104 | - name: Download digests - neo-cli-with-plugins 105 | uses: actions/download-artifact@v4 106 | with: 107 | path: /tmp/digests-plugins-image 108 | pattern: digests-plugins-image-* 109 | merge-multiple: true 110 | 111 | - name: Set up Docker Buildx 112 | uses: docker/setup-buildx-action@v3 113 | 114 | - name: Login to GitHub Container Registry 115 | uses: docker/login-action@v3 116 | with: 117 | registry: ghcr.io 118 | username: ${{ github.actor }} 119 | password: ${{ secrets.GITHUB_TOKEN }} 120 | 121 | - name: Create manifest list and push - neo-cli-with-plugins 122 | working-directory: /tmp/digests-plugins-image 123 | run: | 124 | TAGS="-t ${{ env.IMAGE_ID }}:${{ steps.loadenv.outputs.image-tag }}" 125 | if [[ "${{ github.event.inputs.set-latest-tag }}" == "true" ]]; then 126 | TAGS+=" -t ${{ env.IMAGE_ID }}:latest" 127 | fi 128 | docker buildx imagetools create $TAGS \ 129 | $(printf '${{ env.IMAGE_ID }}@sha256:%s ' *) 130 | 131 | - name: Inspect image - neo-cli-with-plugins 132 | run: | 133 | docker buildx imagetools inspect ${{ env.IMAGE_ID }}:${{ steps.loadenv.outputs.image-tag }} 134 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![License](https://img.shields.io/github/license/AxLabs/neo3-privatenet-docker)](https://github.com/AxLabs/neo3-privatenet-docker/blob/master/LICENSE) 2 | [![GitHub stars](https://img.shields.io/github/stars/AxLabs/neo3-privatenet-docker?style=social)](https://github.com/AxLabs/neo3-privatenet-docker/stargazers) 3 | 4 |
5 |

neo3-privatenet-docker

6 |

7 | :fire::zap::fire::zap::fire: 8 | Run Neo N3 blockchain nodes for development in record time! 9 | :fire::zap::fire::zap::fire: 10 |

11 | 12 |

You're 3 commands away to set up a Neo N3 blockchain private network.

13 |
14 | 15 | ## 🎉 Highlights 16 | 17 | * 💚 This repository relies on [git sub-modules](https://git-scm.com/book/en/v2/Git-Tools-Submodules) pointing to the official [neo](https://github.com/neo-project/neo) repository. Then, you can adjust the reference if you want to rely on the latest or an specific commit! 18 | * 🚀 The neo-cli image is built from a lean [`Dockerfile`](./docker/Dockerfile.neo-node-with-plugins). 19 | * 💯 Includes **all** available plugins from the [neo/src/Plugins](https://github.com/neo-project/neo/tree/master/src/Plugins)! 20 | * 💥 *It just fucking works.* 21 | 22 | ⭐️ Ah, we love GitHub stars to keep our motivation up to the roof! 😉 23 | 24 | ## 🚨 Dependencies 25 | - [docker](https://docs.docker.com/install/): [MacOS](https://docs.docker.com/docker-for-mac/install/) or [Windows](https://docs.docker.com/docker-for-windows/install/) 26 | - [docker-compose](https://docs.docker.com/compose/install/) 27 | 28 | ## 🏃‍♂️ How to Run 29 | 30 | ``` 31 | git clone --recurse-submodules https://github.com/AxLabs/neo3-privatenet-docker.git 32 | cd neo3-privatenet-docker 33 | docker-compose up --pull 34 | ``` 35 | 36 | Then, check the running privatenet: 37 | 38 | ``` 39 | docker ps 40 | ``` 41 | 42 | If you want to stop everything and start from **scratch**: 43 | 44 | ``` 45 | docker-compose down -v 46 | ``` 47 | 48 | After you change something in the config files and want to rebuild everything, without docker cache, run the following: 49 | 50 | ``` 51 | docker-compose build --no-cache 52 | ``` 53 | 54 | ## 🎯 Test a bit through JSON-RPC 55 | 56 | * Get the latest block index of `neo-client1`: 57 | 58 | ``` 59 | curl http://127.0.0.1:10332 -d '{"jsonrpc":"2.0","method":"getblockcount","params":[],"id":1}' 60 | ``` 61 | 62 | * Open the wallet of the `neo-consensus` through JSON-RPC (**only for test purposes!**): 63 | 64 | ``` 65 | curl http://127.0.0.1:40332 -d '{"jsonrpc":"2.0","method":"openwallet","params":["wallet.json","neo"],"id":1}' 66 | ``` 67 | 68 | * List the addresses in `neo-consensus` wallet: 69 | 70 | ``` 71 | curl http://127.0.0.1:40332 -d '{"jsonrpc":"2.0","method":"listaddress","params":[],"id":1}' 72 | ``` 73 | 74 | * Get all NEP-17 balance of `neo-consensus`' address `NXXazKH39yNFWWZF5MJ8tEN98VYHwzn7g3`, specifically: 75 | 76 | ``` 77 | curl http://127.0.0.1:40332 -d '{"jsonrpc":"2.0","method":"getnep17balances","params":["NXXazKH39yNFWWZF5MJ8tEN98VYHwzn7g3"],"id":1}' 78 | ``` 79 | 80 | * Send 100 NEO from `neo-consensus`' address `NXXazKH39yNFWWZF5MJ8tEN98VYHwzn7g3` to `neo-client1`'s address `NdihqSLYTf1B1WYuzhM52MNqvCNPJKLZaz`: 81 | 82 | ``` 83 | curl http://127.0.0.1:40332 -d '{"jsonrpc":"2.0","method":"sendfrom","params":["0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5","NXXazKH39yNFWWZF5MJ8tEN98VYHwzn7g3", "NdihqSLYTf1B1WYuzhM52MNqvCNPJKLZaz",100],"id":1}' 84 | ``` 85 | 86 | * Open the wallet of the `neo-client1` through JSON-RPC (**only for test purposes!**): 87 | 88 | ``` 89 | curl http://127.0.0.1:10332 -d '{"jsonrpc":"2.0","method":"openwallet","params":["wallet.json","neo"],"id":1}' 90 | ``` 91 | 92 | * Get all NEP-17 balance of `neo-client1`' address `NdihqSLYTf1B1WYuzhM52MNqvCNPJKLZaz` (wait 15 seconds before executing the command, due to the block generation interval): 93 | 94 | ``` 95 | curl http://127.0.0.1:10332 -d '{"jsonrpc":"2.0","method":"getnep17balances","params":["NdihqSLYTf1B1WYuzhM52MNqvCNPJKLZaz"],"id":1}' 96 | ``` 97 | 98 | ## 🔨 Useful CLI commands 99 | 100 | This is just a collection of useful CLI commands in case you need them. 101 | 102 | * Designate the Oracle role in the Role Management native contract: 103 | 104 | First, connect to the `neo-consensus`: 105 | 106 | ``` 107 | docker exec -it neo-consensus screen -r 108 | ``` 109 | 110 | Then, in the CLI, enter the following: 111 | 112 | ``` 113 | invoke 0x49cf4e5378ffcd4dec034fd98a174c5491e395e2 designateAsRole [{"type":"Integer","value":8},{"type":"Array","value":[{"type":"PublicKey","value":"02607a38b8010a8f401c25dd01df1b74af1827dd16b821fc07451f2ef7f02da60f"},{"type":"PublicKey","value":"037279f3a507817251534181116cb38ef30468b25074827db34cbbc6adc8873932"}]}] NXXazKH39yNFWWZF5MJ8tEN98VYHwzn7g3 114 | ``` 115 | 116 | If you want to get the list of entries for a particular role: 117 | 118 | ``` 119 | invoke 0x49cf4e5378ffcd4dec034fd98a174c5491e395e2 getDesignatedByRole [{"type":"Integer","value":8},{"type":"Integer","value":10}] NXXazKH39yNFWWZF5MJ8tEN98VYHwzn7g3 120 | ``` 121 | 122 | 👆The second parameter (integer) is the blockchain height. 123 | 124 | ## 💡 Info 125 | 126 | The `docker-compose` file has 3 nodes, each with an account. The consensus node uses one public key for two accounts. One is a multisig account and the other a normal account. The multisig account is required as the validator account. Private keys are encrypted according to NEP-2. 127 | 128 | * **Consensus** 129 | * Address: `NM7Aky765FG8NhhwtxjXRx7jEL1cnw7PBP` 130 | * ScriptHash: `69ecca587293047be4c59159bf8bc399985c160d` 131 | * Script: `0c21033a4d051b04b7fc0230d2b1aaedfd5a84be279a5361a7358db665ad7857787f1b4156e7b327` 132 | * PubKey: `033a4d051b04b7fc0230d2b1aaedfd5a84be279a5361a7358db665ad7857787f1b` 133 | * PrivKey: `84180ac9d6eb6fba207ea4ef9d2200102d1ebeb4b9c07e2c6a738a42742e27a5` 134 | * NEP-2 encrypted: `6PYM7jHL4GmS8Aw2iEFpuaHTCUKjhT4mwVqdoozGU6sUE25BjV4ePXDdLz` 135 | * WIF: `L1eV34wPoj9weqhGijdDLtVQzUpWGHszXXpdU9dPuh2nRFFzFa7E` 136 | * MultiSig Address (from the account above, 1/1): `NXXazKH39yNFWWZF5MJ8tEN98VYHwzn7g3` 137 | * Script: `110c21033a4d051b04b7fc0230d2b1aaedfd5a84be279a5361a7358db665ad7857787f1b11419ed0dc3a` 138 | * ScritpHash: `05859de95ccbbd5668e0f055b208273634d4657f` 139 | * JSON-RPC: `localhost:40332` 140 | * **Client1** 141 | * Address: `NV1Q1dTdvzPbThPbSFz7zudTmsmgnCwX6c` 142 | * Script: `0c2102607a38b8010a8f401c25dd01df1b74af1827dd16b821fc07451f2ef7f02da60f4156e7b327` 143 | * ScripthHash: `88c48eaef7e64b646440da567cd85c9060efbf63` 144 | * PubKey: `02607a38b8010a8f401c25dd01df1b74af1827dd16b821fc07451f2ef7f02da60f` 145 | * PrivKey: `beae38739915555a75a9281a5928b10ebc265f9c881aa21e963610a6c606a3dc` 146 | * NEP-2 encrypted: `6PYWaAbWpf6oeH1VrqtdAGawYMsTfcN1GJyarhUFVEq1siNcRJwMpoo456` 147 | * WIF: `L3cNMQUSrvUrHx1MzacwHiUeCWzqK2MLt5fPvJj9mz6L2rzYZpok` 148 | * JSON-RPC: `localhost:10332` 149 | * **Client2** 150 | * Address: `NhJX9eCbkKtgDrh1S4xMTRaHUGbZ5Be7uU` 151 | * Script: `0c21037279f3a507817251534181116cb38ef30468b25074827db34cbbc6adc88739324156e7b327` 152 | * ScriptHash: `b435bf4b8e34b28a73029eb42d0d99a775799eea` 153 | * PubKey: `037279f3a507817251534181116cb38ef30468b25074827db34cbbc6adc8873932` 154 | * PrivKey: `7d82c818dcc23f9312527b36c4959e5976f5df7a3dec7e1bbb24a45d64d131c1` 155 | * NEP-2 encrypted: `6PYNfKunYGT5sMMqmpkQLB3KRrgvdE2vTEhpXsjQBLFh9cTbRkWkTkz9Q1` 156 | * WIF: `L1RgqMJEBjdXcuYCMYB6m7viQ9zjkNPjZPAKhhBoXxEsygNXENBb` 157 | * JSON-RPC: `localhost:20332` 158 | 159 | * **Wallet passphrase**: `neo` 160 | 161 | * **List of native contract's addresses/hashes**: 162 | * ContractManagement: `0xfffdc93764dbaddd97c48f252a53ea4643faa3fd` 163 | * StdLib: `0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0` 164 | * CryptoLib: `0x726cb6e0cd8628a1350a611384688911ab75f51b` 165 | * LedgerContract: `0xda65b600f7124ce6c79950c1772a36403104f2be` 166 | * NeoToken: `0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5` 167 | * GasToken: `0xd2a4cff31913016155e38e474a2c06d08be276cf` 168 | * PolicyContract: `0xcc5e4edd9f5f8dba8bb65734541df7a1c081c67b` 169 | * RoleManagement: `0x49cf4e5378ffcd4dec034fd98a174c5491e395e2` 170 | * OracleContract: `0xfe924b7cfe89ddd271abaf7210a80a7e11178758` 171 | 172 | * **Address Info**: 173 | * All the addresses have the `AddressVersion` set to `0x35` (which is the [default used in the neo-project](https://github.com/neo-project/neo/blob/402e9b19d80bb9093601f5ac57ff0cdc3c6cf6ab/src/neo/ProtocolSettings.cs#L50)) 174 | 175 | ## 🔜 Upcoming Features 176 | 177 | - [x] Pre-fund wallets of `neo-client1` and `neo-client2` with plenty of NEO and GAS 178 | - [ ] Automatically deploy smart contracts specified in a given local directory 179 | 180 | If you would like to see anything else, give us a shout and [open an issue](https://github.com/AxLabs/neo3-privatenet-docker/issues). 181 | 182 | ## 🙏 Thanks 183 | 184 | * We have to thank [hal0x2328](https://github.com/hal0x2328) for publishing [hal0x2328/neo3-privatenet-tutorial](https://github.com/hal0x2328/neo3-privatenet-tutorial) and inspire us to make things even simpler. 😊 😉 185 | * Thanks for [Tommo-L](https://github.com/Tommo-L) by providing the amazing [Tommo-L/NEO3-Development-Guide](https://github.com/Tommo-L/NEO3-Development-Guide) -- certainly, this development guide is complementary to the [AxLabs/neo3-privatenet-docker](https://github.com/AxLabs/neo3-privatenet-docker) repository. 186 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2020 AxLabs 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------