diff --git a/.gitignore b/.gitignore index 907f72cc..80467331 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.DS_Store target .bsp .idea diff --git a/local-network/.gitignore b/local-network/.gitignore index 658c75d9..1579cb20 100644 --- a/local-network/.gitignore +++ b/local-network/.gitignore @@ -1,5 +1,3 @@ -.DS_Store -.idea .env .cache/ data/ diff --git a/local-network/README.md b/local-network/README.md index 392002fb..bda98739 100644 --- a/local-network/README.md +++ b/local-network/README.md @@ -29,7 +29,7 @@ See [./deploy](./deploy/). # Keys * Node HTTP API Key: `testapi` -* CL accounts (see [genesis-template.conf](./configs/wavesnode/common/genesis-template.conf) for more information): +* CL accounts (see [genesis-template.conf](configs/wavesnode/genesis-template.conf) for more information): * Node wallet seed: * wavesnode-1: `devnet-1` * wavesnode-2: `devnet-2` @@ -43,7 +43,7 @@ See [./deploy](./deploy/). * Address: `0xcF0b9E13FDd593f4Ca26D36aFCaA44dd3FDCCbeD` * Private key: `ab49fee4fc326ecbc7abc7f2e5870bf1f86076eb0979c524e20c843f2a73f647` * To see all information, run `npx tsx common-settings-show.ts` from [./deploy](./deploy/) directory. -* Ethereum addresses and private keys for `besu` nodes in [config](./configs/besu/generated/genesis.json): +* Ethereum addresses and private keys for `besu` nodes in [config](configs/ec-common/genesis.json): * `fe3b557e8fb62b89f4916b721be55ceb828dbd73`: `8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63` * `f17f52151EbEF6C7334FAD080c5704D77216b732`: `ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f` @@ -57,6 +57,8 @@ a non-empty balance. So you can use them to issue transactions on EL. * wavesnode-1: http://127.0.0.1:16869/ * wavesnode-2: http://127.0.0.1:26869/ +If you need a JWT token for authenticated APIs, use [generate.sh](configs/ec-common/generate.sh). + # How to set up Metamask Settings: @@ -100,5 +102,5 @@ See [Besu configuration](configs/besu/). ## How to change Waves initial miners or time between blocks -1. Update [genesis-template.conf](./configs/wavesnode/common/genesis-template.conf). -2. [genesis.conf](./configs/wavesnode/common/genesis.conf) will be updated in [restart.sh](./restart.sh). +1. Update [genesis-template.conf](configs/wavesnode/genesis-template.conf). +2. [genesis.conf](configs/wavesnode/genesis.conf) will be updated in [restart.sh](./restart.sh). diff --git a/local-network/configs/besu/README.md b/local-network/configs/besu/README.md index 038dc6d6..73dfe46c 100644 --- a/local-network/configs/besu/README.md +++ b/local-network/configs/besu/README.md @@ -1,8 +1,5 @@ # Besu configs -Use [./generate-configs.sh](generate-configs.sh) to generate `genesis.json` and keys for nodes. -Note: it always generates new keys! So, don't use it if you don't need to add nodes. - ## Manual connecting Follow [https://besu.hyperledger.org/stable/private-networks/tutorials/permissioning](instructions): diff --git a/local-network/configs/besu/besu-2.conf b/local-network/configs/besu/besu-2.conf deleted file mode 100644 index edafcbab..00000000 --- a/local-network/configs/besu/besu-2.conf +++ /dev/null @@ -1,41 +0,0 @@ -data-path = "/opt/besu/data" -genesis-file = "/config/generated/genesis.json" -node-private-key-file = "/config/generated/keys/0xcfff36559885b5541258c3de97b63dc59a60a583/key" - -sync-mode = "FULL" -host-allowlist = ["*"] -logging = "ALL" -auto-log-bloom-caching-enabled = true -data-storage-format = "BONSAI" -bonsai-limit-trie-logs-enabled = false - -# json-pretty-print-enabled = true # Use jq instead - -graphql-http-enabled = true -revert-reason-enabled = true - -rpc-http-enabled = true -rpc-http-host = "0.0.0.0" -rpc-http-port = 8545 -rpc-http-cors-origins = ["*"] - -engine-rpc-enabled = true -engine-rpc-port = 8551 -engine-host-allowlist = ["*"] -engine-jwt-disabled = true - -rpc-ws-enabled = true -rpc-http-api = ["ADMIN", "CLIQUE", "DEBUG", "EEA", "ETH", "IBFT", "MINER", "NET", "PERM", "PLUGINS", "PRIV", "QBFT", "TRACE", "TXPOOL", "WEB3"] - -p2p-enabled = true -p2p-port = 30303 -discovery-enabled = true -nat-method = "NONE" -Xdns-enabled = true -Xdns-update-enabled = true -bootnodes = [ - "enode://b2ce9caff5e7472eafaf006904e2cb39cdd79801cda1328c510118cafdb0e9574526af6d05a89dae07a376606227c54c724cab1e88edf43190b7544976b275b8@besu-1:30303", - "enode://4e355eebfd77e5c2c0c20328c2bd5f3fde033c58e06e758c3e0a4ad88e8ced176f0d5eb32e214461b73e014591587f7c6567ee373e9c389b872a6d97d74a913c@besu-1:30303" -] - -tx-pool-max-future-by-sender = "1250" diff --git a/local-network/configs/besu/besu-1.conf b/local-network/configs/besu/besu.conf similarity index 56% rename from local-network/configs/besu/besu-1.conf rename to local-network/configs/besu/besu.conf index 33b55801..65846933 100644 --- a/local-network/configs/besu/besu-1.conf +++ b/local-network/configs/besu/besu.conf @@ -1,8 +1,8 @@ # /opt/besu belongs to besu user: https://github.com/hyperledger/besu/blob/main/docker/openjdk-17/Dockerfile # so it is the only writable path data-path = "/opt/besu/data" -genesis-file = "/config/generated/genesis.json" -node-private-key-file = "/config/generated/keys/0x71b67256532de0cb71609d1cf107744b7d0ed1bb/key" +genesis-file = "/genesis.json" +node-private-key-file = "/etc/secrets/p2p-key" sync-mode = "FULL" host-allowlist = ["*"] @@ -20,6 +20,8 @@ rpc-http-enabled = true rpc-http-host = "0.0.0.0" rpc-http-port = 8545 rpc-http-cors-origins = ["*"] +# Disabled: ["EEA", "PRIV"] +rpc-http-api = ["ADMIN", "CLIQUE", "DEBUG", "ETH", "IBFT", "MINER", "NET", "PERM", "PLUGINS", "QBFT", "TRACE", "TXPOOL", "WEB3"] engine-rpc-enabled = true engine-rpc-port = 8551 @@ -27,17 +29,17 @@ engine-host-allowlist = ["*"] engine-jwt-disabled = true rpc-ws-enabled = true -rpc-http-api = ["ADMIN", "CLIQUE", "DEBUG", "EEA", "ETH", "IBFT", "MINER", "NET", "PERM", "PLUGINS", "PRIV", "QBFT", "TRACE", "TXPOOL", "WEB3"] +rpc-ws-api = ["ADMIN", "CLIQUE", "DEBUG", "ETH", "IBFT", "MINER", "NET", "PERM", "PLUGINS", "QBFT", "TRACE", "TXPOOL", "WEB3"] p2p-enabled = true +p2p-interface = "0.0.0.0" +# p2p-host = "see run-besu.sh" p2p-port = 30303 + discovery-enabled = true -nat-method = "NONE" + Xdns-enabled = true Xdns-update-enabled = true -bootnodes = [ - "enode://b2ce9caff5e7472eafaf006904e2cb39cdd79801cda1328c510118cafdb0e9574526af6d05a89dae07a376606227c54c724cab1e88edf43190b7544976b275b8@besu-1:30303", - "enode://4e355eebfd77e5c2c0c20328c2bd5f3fde033c58e06e758c3e0a4ad88e8ced176f0d5eb32e214461b73e014591587f7c6567ee373e9c389b872a6d97d74a913c@besu-2:30303" -] +# bootnodes = [ see BESU_BOOTNODES in peers.env ] tx-pool-max-future-by-sender = "1250" diff --git a/local-network/configs/besu/besu.yml b/local-network/configs/besu/besu.yml new file mode 100644 index 00000000..95b693d8 --- /dev/null +++ b/local-network/configs/besu/besu.yml @@ -0,0 +1,12 @@ +services: + besu: + image: hyperledger/besu:latest # Debug version: besu-debug:latest , see _debug/ + volumes: + - ../ec-common/genesis.json:/genesis.json:ro + - .:/config:ro + - ./run-besu.sh:/tmp/run.sh:ro + env_file: + - ../ec-common/peers.env + environment: + LOG4J_CONFIGURATION_FILE: /config/log4j2.xml + entrypoint: /tmp/run.sh diff --git a/local-network/configs/besu/generate-configs.sh b/local-network/configs/besu/generate-configs.sh deleted file mode 100755 index 2e3712fc..00000000 --- a/local-network/configs/besu/generate-configs.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -DIR="$(cd "$(dirname "$0")" && pwd)" -cd "${DIR}" || exit - -docker run -it --rm -v ${DIR}:/result hyperledger/besu:latest \ - operator generate-blockchain-config \ - --config-file=/result/network-config.json \ - --to=/result/generated \ - --private-key-file-name=key diff --git a/local-network/configs/besu/generated/genesis.json b/local-network/configs/besu/generated/genesis.json deleted file mode 100644 index e0ac1620..00000000 --- a/local-network/configs/besu/generated/genesis.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "config": { - "terminalTotalDifficulty": 0, - "homesteadBlock": 0, - "daoForkBlock": 0, - "eip150Block": 0, - "eip158Block": 0, - "byzantiumBlock": 0, - "petersburgBlock": 0, - "istanbulBlock": 0, - "muirGlacierBlock": 0, - "berlinBlock": 0, - "londonBlock": 0, - "arrowGlacierBlock": 0, - "grayGlacierBlock": 0, - "shanghaiTime": 0, - "cancunTime": 0, - "ethash": {}, - "chainID": 1337 - }, - "nonce": "0x42", - "gasLimit": "0x1000000", - "difficulty": "0x0", - "coinbase": "0x0000000000000000000000000000000000000000", - "alloc": { - "fe3b557e8fb62b89f4916b721be55ceb828dbd73": { - "privateKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", - "//": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", - "balance": "0xad78ebc5ac6200000" - }, - "f17f52151EbEF6C7334FAD080c5704D77216b732": { - "privateKey": "ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f", - "//": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", - "balance": "90000000000000000000000" - }, - "1000000000000000000000000000000000000000": { - "//1": "Bridge contract. To get new code, run: bridge-compile.sh", - "//2": "To update get storage, see the storage layout and setup primitive fields. Or use 0xweb: https://stackoverflow.com/a/76490163", - "code": "60806040526004361061006e575f3560e01c806396f396c31161004c57806396f396c3146100e3578063c4a4326d14610105578063e984df0e1461011d578063fccc281314610131575f80fd5b806339dd5d1b146100725780637157405a146100b957806378338413146100ce575b5f80fd5b34801561007d575f80fd5b506100a161008c36600461059e565b5f6020819052908152604090205461ffff1681565b60405161ffff90911681526020015b60405180910390f35b3480156100c4575f80fd5b506100a161040081565b6100e16100dc3660046105b5565b61015c565b005b3480156100ee575f80fd5b506100f761044e565b6040519081526020016100b0565b348015610110575f80fd5b506100f76402540be40081565b348015610128575f80fd5b506100f7610468565b34801561013c575f80fd5b506101445f81565b6040516001600160a01b0390911681526020016100b0565b61016c6402540be40060016105fc565b34101561017834610478565b61019061018b6402540be40060016105fc565b610478565b6040516020016101a1929190610630565b604051602081830303815290604052906101d75760405162461bcd60e51b81526004016101ce9190610688565b60405180910390fd5b506101ef6402540be400677fffffffffffffff6105fc565b3411156101fb34610478565b61021561018b6402540be400677fffffffffffffff6105fc565b6040516020016102269291906106bd565b604051602081830303815290604052906102535760405162461bcd60e51b81526004016101ce9190610688565b50435f8181526020819052604090205461ffff166104009081119061027790610478565b604051602001610287919061070c565b604051602081830303815290604052906102b45760405162461bcd60e51b81526004016101ce9190610688565b505f818152602081905260408120805461ffff16916102d283610786565b91906101000a81548161ffff021916908361ffff160217905550505f6402540be400346102ff91906107a6565b9050346103116402540be400836105fc565b1461031b34610478565b6103296402540be400610478565b60405160200161033a9291906107c5565b604051602081830303815290604052906103675760405162461bcd60e51b81526004016101ce9190610688565b506040515f90819034908281818185825af1925050503d805f81146103a7576040519150601f19603f3d011682016040523d82523d5f602084013e6103ac565b606091505b50509050806103fd5760405162461bcd60e51b815260206004820152601e60248201527f4661696c656420746f2073656e6420746f206275726e2061646472657373000060448201526064016101ce565b604080516bffffffffffffffffffffffff1986168152600784900b60208201527ffeadaf04de8d7c2594453835b9a93b747e20e7a09a7fdb9280579a6dbaf131a8910160405180910390a150505050565b6104656402540be400677fffffffffffffff6105fc565b81565b6104656402540be40060016105fc565b6060815f0361049e5750506040805180820190915260018152600360fc1b602082015290565b815f5b81156104c757806104b181610814565b91506104c09050600a836107a6565b91506104a1565b5f8167ffffffffffffffff8111156104e1576104e161082c565b6040519080825280601f01601f19166020018201604052801561050b576020820181803683370190505b509050815b851561059557610521600182610840565b90505f61052f600a886107a6565b61053a90600a6105fc565b6105449088610840565b61054f906030610853565b90505f8160f81b90508084848151811061056b5761056b61086c565b60200101906001600160f81b03191690815f1a90535061058c600a896107a6565b97505050610510565b50949350505050565b5f602082840312156105ae575f80fd5b5035919050565b5f602082840312156105c5575f80fd5b81356bffffffffffffffffffffffff19811681146105e1575f80fd5b9392505050565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417610613576106136105e8565b92915050565b5f81518060208401855e5f93019283525090919050565b6a029b2b73a103b30b63ab2960ad1b81525f61064f600b830185610619565b7f206d7573742062652067726561746572206f7220657175616c20746f20000000815261067f601d820185610619565b95945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b6a029b2b73a103b30b63ab2960ad1b81525f6106dc600b830185610619565b7f206d757374206265206c657373206f7220657175616c20746f20000000000000815261067f601a820185610619565b7f4d6178207472616e7366657273206c696d6974206f662000000000000000000081525f61073d6017830184610619565b7f207265616368656420696e207468697320626c6f636b2e2054727920746f207381527232b732103a3930b739b332b9399030b3b0b4b760691b60208201526033019392505050565b5f61ffff821661ffff810361079d5761079d6105e8565b60010192915050565b5f826107c057634e487b7160e01b5f52601260045260245ffd5b500490565b6a029b2b73a103b30b63ab2960ad1b81525f6107e4600b830185610619565b7f206d7573742062652061206d756c7469706c65206f6620000000000000000000815261067f6017820185610619565b5f60018201610825576108256105e8565b5060010190565b634e487b7160e01b5f52604160045260245ffd5b81810381811115610613576106136105e8565b60ff8181168382160190811115610613576106136105e8565b634e487b7160e01b5f52603260045260245ffdfea2646970667358221220106399f534da089226c14e2f183f8421d059a924c65c97d7e4f3e931c54fe1bb64736f6c634300081a0033" - } - } -} diff --git a/local-network/configs/besu/generated/keys/0x71b67256532de0cb71609d1cf107744b7d0ed1bb/key b/local-network/configs/besu/generated/keys/0x71b67256532de0cb71609d1cf107744b7d0ed1bb/key deleted file mode 100644 index 8519dea0..00000000 --- a/local-network/configs/besu/generated/keys/0x71b67256532de0cb71609d1cf107744b7d0ed1bb/key +++ /dev/null @@ -1 +0,0 @@ -0xc69c6f46a2bf7024c3805bb38b2e96d2bbacd065a4951d1bd2d2d5957838eb65 \ No newline at end of file diff --git a/local-network/configs/besu/generated/keys/0x71b67256532de0cb71609d1cf107744b7d0ed1bb/key.pub b/local-network/configs/besu/generated/keys/0x71b67256532de0cb71609d1cf107744b7d0ed1bb/key.pub deleted file mode 100644 index 4c68b29e..00000000 --- a/local-network/configs/besu/generated/keys/0x71b67256532de0cb71609d1cf107744b7d0ed1bb/key.pub +++ /dev/null @@ -1 +0,0 @@ -0xb2ce9caff5e7472eafaf006904e2cb39cdd79801cda1328c510118cafdb0e9574526af6d05a89dae07a376606227c54c724cab1e88edf43190b7544976b275b8 \ No newline at end of file diff --git a/local-network/configs/besu/generated/keys/0xcfff36559885b5541258c3de97b63dc59a60a583/key b/local-network/configs/besu/generated/keys/0xcfff36559885b5541258c3de97b63dc59a60a583/key deleted file mode 100644 index def476c5..00000000 --- a/local-network/configs/besu/generated/keys/0xcfff36559885b5541258c3de97b63dc59a60a583/key +++ /dev/null @@ -1 +0,0 @@ -0x93ce9a6ca2750272f118afef441fa0d9943f543118a7a51fe6104e651a88207c \ No newline at end of file diff --git a/local-network/configs/besu/generated/keys/0xcfff36559885b5541258c3de97b63dc59a60a583/key.pub b/local-network/configs/besu/generated/keys/0xcfff36559885b5541258c3de97b63dc59a60a583/key.pub deleted file mode 100644 index 274a3491..00000000 --- a/local-network/configs/besu/generated/keys/0xcfff36559885b5541258c3de97b63dc59a60a583/key.pub +++ /dev/null @@ -1 +0,0 @@ -0x4e355eebfd77e5c2c0c20328c2bd5f3fde033c58e06e758c3e0a4ad88e8ced176f0d5eb32e214461b73e014591587f7c6567ee373e9c389b872a6d97d74a913c \ No newline at end of file diff --git a/local-network/configs/besu/log4j2.xml b/local-network/configs/besu/log4j2.xml index 6364c7fd..6309ddbb 100644 --- a/local-network/configs/besu/log4j2.xml +++ b/local-network/configs/besu/log4j2.xml @@ -10,7 +10,7 @@ - + diff --git a/local-network/configs/besu/run-besu.sh b/local-network/configs/besu/run-besu.sh new file mode 100755 index 00000000..09c6009e --- /dev/null +++ b/local-network/configs/besu/run-besu.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env sh + +IP=$(hostname -I) + +# --p2p-host="ec-1" # Doesn't work: https://github.com/hyperledger/besu/issues/4380 +besu \ + --config-file=/config/besu.conf \ + --p2p-host=${IP} diff --git a/local-network/configs/blockscout/backend/bs-backend.env b/local-network/configs/blockscout/backend/bs-backend.env index 277f3c07..cc95fc58 100644 --- a/local-network/configs/blockscout/backend/bs-backend.env +++ b/local-network/configs/blockscout/backend/bs-backend.env @@ -1,9 +1,9 @@ ETHEREUM_JSONRPC_VARIANT=besu -ETHEREUM_JSONRPC_HTTP_URL=http://besu-1:8545/ +ETHEREUM_JSONRPC_HTTP_URL=http://ec-1:8545/ # ETHEREUM_JSONRPC_FALLBACK_HTTP_URL= DATABASE_URL=postgresql://blockscout:ceWb1MeLBEeOIfk65gU8EjF8@db:5432/blockscout # DATABASE_QUEUE_TARGET -ETHEREUM_JSONRPC_TRACE_URL=http://besu:8545/ +ETHEREUM_JSONRPC_TRACE_URL=http://ec-1:8545/ # ETHEREUM_JSONRPC_FALLBACK_TRACE_URL= # ETHEREUM_JSONRPC_ETH_CALL_URL= # ETHEREUM_JSONRPC_HTTP_TIMEOUT= @@ -11,7 +11,7 @@ ETHEREUM_JSONRPC_TRACE_URL=http://besu:8545/ NETWORK= SUBNETWORK=Awesome chain LOGO=/images/blockscout_logo.svg -ETHEREUM_JSONRPC_WS_URL=ws://besu-1:8546/ +ETHEREUM_JSONRPC_WS_URL=ws://ec-1:8546/ ETHEREUM_JSONRPC_TRANSPORT=http ETHEREUM_JSONRPC_DISABLE_ARCHIVE_BALANCES=false # ETHEREUM_JSONRPC_ARCHIVE_BALANCES_WINDOW=200 diff --git a/local-network/configs/blockscout/enabled.yml b/local-network/configs/blockscout/enabled.yml index 8253b2e4..732b18a5 100644 --- a/local-network/configs/blockscout/enabled.yml +++ b/local-network/configs/blockscout/enabled.yml @@ -21,7 +21,7 @@ services: depends_on: - db - redis - - besu-1 + - ec-1 extends: file: ./backend/backend.yml service: backend diff --git a/local-network/configs/blockscout/nginx/nginx.yml b/local-network/configs/blockscout/nginx/nginx.yml index 7dcfd0f8..2a034586 100644 --- a/local-network/configs/blockscout/nginx/nginx.yml +++ b/local-network/configs/blockscout/nginx/nginx.yml @@ -10,11 +10,11 @@ services: environment: BACK_PROXY_PASS: ${BACK_PROXY_PASS:-http://bs-backend:4000} FRONT_PROXY_PASS: ${FRONT_PROXY_PASS:-http://bs-frontend:3000} - BESU_RPC_PROXY_PASS: ${BESU_RPC_PROXY_PASS:-http://besu-1:8545} - BESU_WS_PROXY_PASS: ${BESU_WS_PROXY_PASS:-http://besu-1:8546} + BESU_RPC_PROXY_PASS: ${BESU_RPC_PROXY_PASS:-http://ec-1:8545} + BESU_WS_PROXY_PASS: ${BESU_WS_PROXY_PASS:-http://ec-1:8546} WAVES_PROXY_PASS: ${WAVES_PROXY_PASS:-http://wavesnode-1:6869} ports: - - '0.0.0.0:3000:3000' - - '0.0.0.0:3001:3001' - - '0.0.0.0:3002:3002' - - '0.0.0.0:10001:10001' + - '127.0.0.1:3000:3000' + - '127.0.0.1:3001:3001' + - '127.0.0.1:3002:3002' + - '127.0.0.1:10001:10001' diff --git a/local-network/configs/ec-common/.gitignore b/local-network/configs/ec-common/.gitignore new file mode 100644 index 00000000..c1e6509a --- /dev/null +++ b/local-network/configs/ec-common/.gitignore @@ -0,0 +1 @@ +jwt-token-*.hex diff --git a/local-network/configs/ec-common/generate.sh b/local-network/configs/ec-common/generate.sh new file mode 100755 index 00000000..d5bf0a0d --- /dev/null +++ b/local-network/configs/ec-common/generate.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +DIR="$(cd "$(dirname "$0")" && pwd)" +cd "${DIR}" || exit + +for N in {1..4}; do + p2p_file="p2p-key-${N}.hex" + jwt_file="jwt-secret-${N}.hex" + jwt_token_file="jwt-token-${N}.hex" + + # Generate p2p key without newline + if [ ! -f "$p2p_file" ]; then + openssl rand 32 | xxd -p -c 32 | tr -d '\n' > "$p2p_file" + echo "Created $p2p_file" + fi + + # Generate JWT secret without newline + if [ ! -f "$jwt_file" ]; then + openssl rand 32 | xxd -p -c 32 | tr -d '\n' > "$jwt_file" + echo "Created $jwt_file" + fi + + # Generate JWT token + secret=$(cat "$jwt_file") + ./jwt-token-generate.sh "$secret" > "$jwt_token_file" + echo "Generated JWT token in $jwt_token_file" +done diff --git a/local-network/configs/besu/network-config.json b/local-network/configs/ec-common/genesis.json similarity index 72% rename from local-network/configs/besu/network-config.json rename to local-network/configs/ec-common/genesis.json index 4a836549..6e586158 100644 --- a/local-network/configs/besu/network-config.json +++ b/local-network/configs/ec-common/genesis.json @@ -1,50 +1,46 @@ { - "genesis": { - "config": { - "terminalTotalDifficulty": 0, - "homesteadBlock": 0, - "daoForkBlock": 0, - "eip150Block": 0, - "eip158Block": 0, - "byzantiumBlock": 0, - "petersburgBlock": 0, - "istanbulBlock": 0, - "muirGlacierBlock": 0, - "berlinBlock": 0, - "londonBlock": 0, - "arrowGlacierBlock": 0, - "grayGlacierBlock": 0, - "shanghaiTime": 0, - "cancunTime": 0, - "ethash": {}, - "chainID": 1337 - }, - "nonce": "0x42", - "gasLimit": "0x1000000", - "difficulty": "0x0", - "coinbase": "0x0000000000000000000000000000000000000000", - "alloc": { - "fe3b557e8fb62b89f4916b721be55ceb828dbd73": { - "privateKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", - "//": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", - "balance": "0xad78ebc5ac6200000" - }, - "f17f52151EbEF6C7334FAD080c5704D77216b732": { - "privateKey": "ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f", - "//": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", - "balance": "90000000000000000000000" - }, - "1000000000000000000000000000000000000000": { - "//1": "Bridge contract. To get new code, run: bridge-compile.sh", - "//2": "To update get storage, see the storage layout and setup primitive fields. Or use 0xweb: https://stackoverflow.com/a/76490163", - "code": "60806040526004361061006e575f3560e01c806396f396c31161004c57806396f396c3146100e3578063c4a4326d14610105578063e984df0e1461011d578063fccc281314610131575f80fd5b806339dd5d1b146100725780637157405a146100b957806378338413146100ce575b5f80fd5b34801561007d575f80fd5b506100a161008c36600461059e565b5f6020819052908152604090205461ffff1681565b60405161ffff90911681526020015b60405180910390f35b3480156100c4575f80fd5b506100a161040081565b6100e16100dc3660046105b5565b61015c565b005b3480156100ee575f80fd5b506100f761044e565b6040519081526020016100b0565b348015610110575f80fd5b506100f76402540be40081565b348015610128575f80fd5b506100f7610468565b34801561013c575f80fd5b506101445f81565b6040516001600160a01b0390911681526020016100b0565b61016c6402540be40060016105fc565b34101561017834610478565b61019061018b6402540be40060016105fc565b610478565b6040516020016101a1929190610630565b604051602081830303815290604052906101d75760405162461bcd60e51b81526004016101ce9190610688565b60405180910390fd5b506101ef6402540be400677fffffffffffffff6105fc565b3411156101fb34610478565b61021561018b6402540be400677fffffffffffffff6105fc565b6040516020016102269291906106bd565b604051602081830303815290604052906102535760405162461bcd60e51b81526004016101ce9190610688565b50435f8181526020819052604090205461ffff166104009081119061027790610478565b604051602001610287919061070c565b604051602081830303815290604052906102b45760405162461bcd60e51b81526004016101ce9190610688565b505f818152602081905260408120805461ffff16916102d283610786565b91906101000a81548161ffff021916908361ffff160217905550505f6402540be400346102ff91906107a6565b9050346103116402540be400836105fc565b1461031b34610478565b6103296402540be400610478565b60405160200161033a9291906107c5565b604051602081830303815290604052906103675760405162461bcd60e51b81526004016101ce9190610688565b506040515f90819034908281818185825af1925050503d805f81146103a7576040519150601f19603f3d011682016040523d82523d5f602084013e6103ac565b606091505b50509050806103fd5760405162461bcd60e51b815260206004820152601e60248201527f4661696c656420746f2073656e6420746f206275726e2061646472657373000060448201526064016101ce565b604080516bffffffffffffffffffffffff1986168152600784900b60208201527ffeadaf04de8d7c2594453835b9a93b747e20e7a09a7fdb9280579a6dbaf131a8910160405180910390a150505050565b6104656402540be400677fffffffffffffff6105fc565b81565b6104656402540be40060016105fc565b6060815f0361049e5750506040805180820190915260018152600360fc1b602082015290565b815f5b81156104c757806104b181610814565b91506104c09050600a836107a6565b91506104a1565b5f8167ffffffffffffffff8111156104e1576104e161082c565b6040519080825280601f01601f19166020018201604052801561050b576020820181803683370190505b509050815b851561059557610521600182610840565b90505f61052f600a886107a6565b61053a90600a6105fc565b6105449088610840565b61054f906030610853565b90505f8160f81b90508084848151811061056b5761056b61086c565b60200101906001600160f81b03191690815f1a90535061058c600a896107a6565b97505050610510565b50949350505050565b5f602082840312156105ae575f80fd5b5035919050565b5f602082840312156105c5575f80fd5b81356bffffffffffffffffffffffff19811681146105e1575f80fd5b9392505050565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417610613576106136105e8565b92915050565b5f81518060208401855e5f93019283525090919050565b6a029b2b73a103b30b63ab2960ad1b81525f61064f600b830185610619565b7f206d7573742062652067726561746572206f7220657175616c20746f20000000815261067f601d820185610619565b95945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b6a029b2b73a103b30b63ab2960ad1b81525f6106dc600b830185610619565b7f206d757374206265206c657373206f7220657175616c20746f20000000000000815261067f601a820185610619565b7f4d6178207472616e7366657273206c696d6974206f662000000000000000000081525f61073d6017830184610619565b7f207265616368656420696e207468697320626c6f636b2e2054727920746f207381527232b732103a3930b739b332b9399030b3b0b4b760691b60208201526033019392505050565b5f61ffff821661ffff810361079d5761079d6105e8565b60010192915050565b5f826107c057634e487b7160e01b5f52601260045260245ffd5b500490565b6a029b2b73a103b30b63ab2960ad1b81525f6107e4600b830185610619565b7f206d7573742062652061206d756c7469706c65206f6620000000000000000000815261067f6017820185610619565b5f60018201610825576108256105e8565b5060010190565b634e487b7160e01b5f52604160045260245ffd5b81810381811115610613576106136105e8565b60ff8181168382160190811115610613576106136105e8565b634e487b7160e01b5f52603260045260245ffdfea2646970667358221220106399f534da089226c14e2f183f8421d059a924c65c97d7e4f3e931c54fe1bb64736f6c634300081a0033" - } - } + "config": { + "chainID": 1337, + "arrowGlacierBlock": 0, + "berlinBlock": 0, + "byzantiumBlock": 0, + "cancunTime": 0, + "constantinopleBlock": 0, + "daoForkBlock": 0, + "eip150Block": 0, + "eip155Block": 0, + "eip158Block": 0, + "ethash": {}, + "grayGlacierBlock": 0, + "homesteadBlock": 0, + "istanbulBlock": 0, + "londonBlock": 0, + "muirGlacierBlock": 0, + "petersburgBlock": 0, + "shanghaiTime": 0, + "terminalTotalDifficulty": 0, + "terminalTotalDifficultyPassed": true }, - "blockchain": { - "nodes": { - "generate": true, - "count": 2 + "nonce": "0x42", + "gasLimit": "0x1000000", + "difficulty": "0x0", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": { + "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73": { + "privateKey": "0x8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", + "//": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", + "balance": "0xad78ebc5ac6200000" + }, + "0xf17f52151EbEF6C7334FAD080c5704D77216b732": { + "privateKey": "0xae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f", + "//": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", + "balance": "90000000000000000000000" + }, + "0x1000000000000000000000000000000000000000": { + "//1": "Bridge contract. To get new code, run: bridge-compile.sh", + "//2": "To update get storage, see the storage layout and setup primitive fields. Or use 0xweb: https://stackoverflow.com/a/76490163", + "code": "0x60806040526004361061006e575f3560e01c806396f396c31161004c57806396f396c3146100e3578063c4a4326d14610105578063e984df0e1461011d578063fccc281314610131575f80fd5b806339dd5d1b146100725780637157405a146100b957806378338413146100ce575b5f80fd5b34801561007d575f80fd5b506100a161008c36600461059e565b5f6020819052908152604090205461ffff1681565b60405161ffff90911681526020015b60405180910390f35b3480156100c4575f80fd5b506100a161040081565b6100e16100dc3660046105b5565b61015c565b005b3480156100ee575f80fd5b506100f761044e565b6040519081526020016100b0565b348015610110575f80fd5b506100f76402540be40081565b348015610128575f80fd5b506100f7610468565b34801561013c575f80fd5b506101445f81565b6040516001600160a01b0390911681526020016100b0565b61016c6402540be40060016105fc565b34101561017834610478565b61019061018b6402540be40060016105fc565b610478565b6040516020016101a1929190610630565b604051602081830303815290604052906101d75760405162461bcd60e51b81526004016101ce9190610688565b60405180910390fd5b506101ef6402540be400677fffffffffffffff6105fc565b3411156101fb34610478565b61021561018b6402540be400677fffffffffffffff6105fc565b6040516020016102269291906106bd565b604051602081830303815290604052906102535760405162461bcd60e51b81526004016101ce9190610688565b50435f8181526020819052604090205461ffff166104009081119061027790610478565b604051602001610287919061070c565b604051602081830303815290604052906102b45760405162461bcd60e51b81526004016101ce9190610688565b505f818152602081905260408120805461ffff16916102d283610786565b91906101000a81548161ffff021916908361ffff160217905550505f6402540be400346102ff91906107a6565b9050346103116402540be400836105fc565b1461031b34610478565b6103296402540be400610478565b60405160200161033a9291906107c5565b604051602081830303815290604052906103675760405162461bcd60e51b81526004016101ce9190610688565b506040515f90819034908281818185825af1925050503d805f81146103a7576040519150601f19603f3d011682016040523d82523d5f602084013e6103ac565b606091505b50509050806103fd5760405162461bcd60e51b815260206004820152601e60248201527f4661696c656420746f2073656e6420746f206275726e2061646472657373000060448201526064016101ce565b604080516bffffffffffffffffffffffff1986168152600784900b60208201527ffeadaf04de8d7c2594453835b9a93b747e20e7a09a7fdb9280579a6dbaf131a8910160405180910390a150505050565b6104656402540be400677fffffffffffffff6105fc565b81565b6104656402540be40060016105fc565b6060815f0361049e5750506040805180820190915260018152600360fc1b602082015290565b815f5b81156104c757806104b181610814565b91506104c09050600a836107a6565b91506104a1565b5f8167ffffffffffffffff8111156104e1576104e161082c565b6040519080825280601f01601f19166020018201604052801561050b576020820181803683370190505b509050815b851561059557610521600182610840565b90505f61052f600a886107a6565b61053a90600a6105fc565b6105449088610840565b61054f906030610853565b90505f8160f81b90508084848151811061056b5761056b61086c565b60200101906001600160f81b03191690815f1a90535061058c600a896107a6565b97505050610510565b50949350505050565b5f602082840312156105ae575f80fd5b5035919050565b5f602082840312156105c5575f80fd5b81356bffffffffffffffffffffffff19811681146105e1575f80fd5b9392505050565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417610613576106136105e8565b92915050565b5f81518060208401855e5f93019283525090919050565b6a029b2b73a103b30b63ab2960ad1b81525f61064f600b830185610619565b7f206d7573742062652067726561746572206f7220657175616c20746f20000000815261067f601d820185610619565b95945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b6a029b2b73a103b30b63ab2960ad1b81525f6106dc600b830185610619565b7f206d757374206265206c657373206f7220657175616c20746f20000000000000815261067f601a820185610619565b7f4d6178207472616e7366657273206c696d6974206f662000000000000000000081525f61073d6017830184610619565b7f207265616368656420696e207468697320626c6f636b2e2054727920746f207381527232b732103a3930b739b332b9399030b3b0b4b760691b60208201526033019392505050565b5f61ffff821661ffff810361079d5761079d6105e8565b60010192915050565b5f826107c057634e487b7160e01b5f52601260045260245ffd5b500490565b6a029b2b73a103b30b63ab2960ad1b81525f6107e4600b830185610619565b7f206d7573742062652061206d756c7469706c65206f6620000000000000000000815261067f6017820185610619565b5f60018201610825576108256105e8565b5060010190565b634e487b7160e01b5f52604160045260245ffd5b81810381811115610613576106136105e8565b60ff8181168382160190811115610613576106136105e8565b634e487b7160e01b5f52603260045260245ffdfea2646970667358221220106399f534da089226c14e2f183f8421d059a924c65c97d7e4f3e931c54fe1bb64736f6c634300081a0033", + "balance": "0x0" } } } diff --git a/local-network/configs/ec-common/jwt-secret-1.hex b/local-network/configs/ec-common/jwt-secret-1.hex new file mode 100644 index 00000000..402a3f1e --- /dev/null +++ b/local-network/configs/ec-common/jwt-secret-1.hex @@ -0,0 +1 @@ +ed292c1b8df420f0fed62f9e83e3ca176b88e5723218b83d9e1b36df375e4ac4 \ No newline at end of file diff --git a/local-network/configs/ec-common/jwt-secret-2.hex b/local-network/configs/ec-common/jwt-secret-2.hex new file mode 100644 index 00000000..0a747833 --- /dev/null +++ b/local-network/configs/ec-common/jwt-secret-2.hex @@ -0,0 +1 @@ +a59c7150d727e228fceabfc4497c21d6acbdd083e0063dadcb20e2be661cefb2 \ No newline at end of file diff --git a/local-network/configs/ec-common/jwt-secret-3.hex b/local-network/configs/ec-common/jwt-secret-3.hex new file mode 100644 index 00000000..baa373af --- /dev/null +++ b/local-network/configs/ec-common/jwt-secret-3.hex @@ -0,0 +1 @@ +2703dcfc67b9a772756c4d354e2943fd7e3d8a2cb95b2129faa497b09662780d \ No newline at end of file diff --git a/local-network/configs/ec-common/jwt-secret-4.hex b/local-network/configs/ec-common/jwt-secret-4.hex new file mode 100644 index 00000000..f6799e31 --- /dev/null +++ b/local-network/configs/ec-common/jwt-secret-4.hex @@ -0,0 +1 @@ +e6cba16eb245df8f057f5a3690ce57ed29f39b30d04a07e7de34d1b3b01c4d7e diff --git a/local-network/configs/ec-common/jwt-token-generate.sh b/local-network/configs/ec-common/jwt-token-generate.sh new file mode 100755 index 00000000..86cfdd84 --- /dev/null +++ b/local-network/configs/ec-common/jwt-token-generate.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +if [ -z "$1" ]; then + echo "Usage: $0 " + exit 1 +fi + +hexsecret=$(echo -n "$1" | tr -d '\n') + +base64_url_encode() { + echo -n "$1" | base64 | sed s/\+/-/g | sed 's/\//_/g' | sed -E s/=+$// +} + +jwt_header=$(base64_url_encode '{"alg":"HS256","typ":"JWT"}') + +iat=$(date +%s) # Seconds since 1970-01-01 +payload=$(base64_url_encode "{\"iat\":${iat}}") + +hmac_signature=$(echo -n "${jwt_header}.${payload}" | openssl dgst -sha256 -mac HMAC -macopt hexkey:"${hexsecret}" -binary | base64_url_encode) + +echo -n "${jwt_header}.${payload}.${hmac_signature}" diff --git a/local-network/configs/ec-common/p2p-key-1.hex b/local-network/configs/ec-common/p2p-key-1.hex new file mode 100644 index 00000000..0ba0c55e --- /dev/null +++ b/local-network/configs/ec-common/p2p-key-1.hex @@ -0,0 +1 @@ +c69c6f46a2bf7024c3805bb38b2e96d2bbacd065a4951d1bd2d2d5957838eb65 \ No newline at end of file diff --git a/local-network/configs/ec-common/p2p-key-2.hex b/local-network/configs/ec-common/p2p-key-2.hex new file mode 100644 index 00000000..231d0f0e --- /dev/null +++ b/local-network/configs/ec-common/p2p-key-2.hex @@ -0,0 +1 @@ +93ce9a6ca2750272f118afef441fa0d9943f543118a7a51fe6104e651a88207c \ No newline at end of file diff --git a/local-network/configs/ec-common/p2p-key-3.hex b/local-network/configs/ec-common/p2p-key-3.hex new file mode 100644 index 00000000..fbd82756 --- /dev/null +++ b/local-network/configs/ec-common/p2p-key-3.hex @@ -0,0 +1 @@ +244bb704084d2a49b4fc2da3b27a1c1c76329d7cac6fbadfd8c1a615730d6f77 \ No newline at end of file diff --git a/local-network/configs/ec-common/p2p-key-4.hex b/local-network/configs/ec-common/p2p-key-4.hex new file mode 100644 index 00000000..cd8c6af5 --- /dev/null +++ b/local-network/configs/ec-common/p2p-key-4.hex @@ -0,0 +1 @@ +7c2d9d0bb13ac806701462ab2e1bbcc54eb7b5e8f6658610a6e06dcc30e0aa47 \ No newline at end of file diff --git a/local-network/configs/ec-common/p2p-key-bootnode.hex b/local-network/configs/ec-common/p2p-key-bootnode.hex new file mode 100644 index 00000000..cf2d9f0e --- /dev/null +++ b/local-network/configs/ec-common/p2p-key-bootnode.hex @@ -0,0 +1 @@ +dc51ae50601364b0d9354bad516acd16261447f89bde416399fa4ae5f2cbe8ab \ No newline at end of file diff --git a/local-network/configs/ec-common/peers.env b/local-network/configs/ec-common/peers.env new file mode 100644 index 00000000..110bdc04 --- /dev/null +++ b/local-network/configs/ec-common/peers.env @@ -0,0 +1 @@ +BESU_BOOTNODES=enode://b2ce9caff5e7472eafaf006904e2cb39cdd79801cda1328c510118cafdb0e9574526af6d05a89dae07a376606227c54c724cab1e88edf43190b7544976b275b8@ec-1:30303,enode://4e355eebfd77e5c2c0c20328c2bd5f3fde033c58e06e758c3e0a4ad88e8ced176f0d5eb32e214461b73e014591587f7c6567ee373e9c389b872a6d97d74a913c@ec-2:30303 diff --git a/local-network/configs/geth/geth.yml b/local-network/configs/geth/geth.yml new file mode 100644 index 00000000..7f4fe47c --- /dev/null +++ b/local-network/configs/geth/geth.yml @@ -0,0 +1,15 @@ +services: + geth: + image: ethereum/client-go:stable + stop_grace_period: 10s + entrypoint: /tmp/run.sh + volumes: + - ../ec-common/genesis.json:/tmp/genesis.json:ro + - ./run-geth.sh:/tmp/run.sh:ro + env_file: + - ../ec-common/peers.env + healthcheck: + test: 'wget -qO /dev/null --header "content-type: application/json" --post-data {\"jsonrpc\":\"2.0\",\"method\":\"eth_blockNumber\",\"params\":[],\"id\":1} http://127.0.0.1:8545' + interval: 5s + timeout: 1s + retries: 10 diff --git a/local-network/configs/geth/run-geth.sh b/local-network/configs/geth/run-geth.sh new file mode 100755 index 00000000..b608afd0 --- /dev/null +++ b/local-network/configs/geth/run-geth.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env sh + +if [ ! -d /root/.ethereum/geth ] ; then + geth init /tmp/genesis.json 2>&1 | tee /root/logs/init.log +fi + +IP_RAW=$(ip -4 addr show dev eth0 | awk '/inet / {print $2}') +IP=$(echo "$IP_RAW" | cut -d/ -f1) +NETWORK=$(echo "$IP_RAW" | xargs ipcalc -n | awk -F= '{print $2}') +PREFIX=$(echo "$IP_RAW" | xargs ipcalc -p | awk -F= '{print $2}') + +tee /root/logs/log < - - - - - /var/log/waves/ChainContractSnapshotClient.log - - ${default.pattern} - - - - - - - diff --git a/local-network/configs/wavesnode/common/genesis-template.conf b/local-network/configs/wavesnode/genesis-template.conf similarity index 100% rename from local-network/configs/wavesnode/common/genesis-template.conf rename to local-network/configs/wavesnode/genesis-template.conf diff --git a/local-network/configs/wavesnode/waves-1.conf b/local-network/configs/wavesnode/waves-1.conf deleted file mode 100644 index 281684eb..00000000 --- a/local-network/configs/wavesnode/waves-1.conf +++ /dev/null @@ -1,9 +0,0 @@ -include "common/waves-common.conf" - -waves { - network.node-name = waves-1 - - l2.execution-client-address = besu-1 - - wallet.seed = HnyGuCEnV1A # devnet-1 , addr: 3FNraPMYcfuGREcxorNSEBHgNLjmYtaHy9e -} diff --git a/local-network/configs/wavesnode/waves-2.conf b/local-network/configs/wavesnode/waves-2.conf deleted file mode 100644 index 1b2aa31b..00000000 --- a/local-network/configs/wavesnode/waves-2.conf +++ /dev/null @@ -1,9 +0,0 @@ -include "common/waves-common.conf" - -waves { - network.node-name = "waves-2" - - l2.execution-client-address = besu-2 - - wallet.seed = HnyGuCEnV1B # devnet-2 , addr: 3FSrRN8X7cDsLyYTScS8Yf8KSwZgJBwf1jU -} diff --git a/local-network/configs/wavesnode/common/waves-common.conf b/local-network/configs/wavesnode/waves.conf similarity index 94% rename from local-network/configs/wavesnode/common/waves-common.conf rename to local-network/configs/wavesnode/waves.conf index c3759d40..b7d38280 100644 --- a/local-network/configs/wavesnode/common/waves-common.conf +++ b/local-network/configs/wavesnode/waves.conf @@ -81,6 +81,7 @@ waves { # P2P Network settings network { + node-name = "waves-"${NODE_NUMBER} break-idle-connections-timeout = 10m # Network address @@ -112,6 +113,9 @@ waves { l2 { chain-contract = "3FdaanzgX4roVgHevhq8L8q42E7EZL9XTQr" + execution-client-address = "http://ec-"${NODE_NUMBER}":8551" + jwt-secret-file = "/etc/secrets/jwt-secret-"${NODE_NUMBER}".hex" + network { bind-address = "0.0.0.0" port = 6865 @@ -157,7 +161,10 @@ waves { units.ConsensusClient ] - wallet.password = "" + wallet { + seed = ${WAVES_WALLET_SEED} + password = "" + } } kamon.enable = no diff --git a/local-network/configs/wavesnode/wavesnode.yml b/local-network/configs/wavesnode/wavesnode.yml new file mode 100644 index 00000000..8d7c9a2d --- /dev/null +++ b/local-network/configs/wavesnode/wavesnode.yml @@ -0,0 +1,13 @@ +services: + wavesnode: + image: unitsnetwork/consensus-client:main + pull_policy: never + environment: + JAVA_OPTS: -Dlogback.file.level=TRACE + WAVES_LOG_LEVEL: TRACE + WAVES_HEAP_SIZE: 2g + # NODE_NUMBER: + # WAVES_WALLET_SEED: + volumes: + - ./:/etc/waves:ro + - ../ec-common:/etc/secrets:ro diff --git a/local-network/deploy/package-lock.json b/local-network/deploy/package-lock.json index ded79620..98f9bda1 100644 --- a/local-network/deploy/package-lock.json +++ b/local-network/deploy/package-lock.json @@ -6,22 +6,23 @@ "": { "name": "l1-deploy-scripts", "dependencies": { - "@types/node": "^20.12.12", + "@types/node": "^22.5", "@waves/node-api-js": "^1.3.11-beta.1", "@waves/ts-lib-crypto": "^1.4.4-beta.1", - "@waves/waves-transactions": "^4.3.11", - "merkletreejs": "^0.3.11", - "solc": "0.8.25", - "tsx": "^4.10.2", - "typescript": "^4.9.5", - "web3": "^4.7.0", - "winston": "^3.13.0" + "@waves/waves-transactions": "^4.3", + "merkletreejs": "^0.4", + "solc": "0.8.27", + "tsx": "^4.19", + "typescript": "^5.5", + "web3": "^4.12", + "winston": "^3.14" } }, "node_modules/@adraffy/ens-normalize": { "version": "1.10.1", "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", - "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==" + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", + "license": "MIT" }, "node_modules/@colors/colors": { "version": "1.6.0", @@ -42,18 +43,19 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", - "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", + "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@ethereumjs/rlp": { @@ -200,11 +202,12 @@ "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" }, "node_modules/@types/node": { - "version": "20.12.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", - "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", + "version": "22.5.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", + "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } }, "node_modules/@types/node-fetch": { @@ -225,6 +228,7 @@ "version": "8.5.3", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -336,6 +340,7 @@ "version": "0.7.1", "resolved": "https://registry.npmjs.org/abitype/-/abitype-0.7.1.tgz", "integrity": "sha512-VBkRHTDZf9Myaek/dO3yMmOzB/y2s3Zo6nVU7yaw1G+TvCHAjwaJzNGN9yo4K5D8bU/VZXKP1EJpRhFr862PlQ==", + "license": "MIT", "peerDependencies": { "typescript": ">=4.9.4", "zod": "^3 >=3.19.1" @@ -502,6 +507,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "license": "Apache-2.0", "bin": { "crc32": "bin/crc32.njs" }, @@ -513,6 +519,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", + "license": "MIT", "dependencies": { "node-fetch": "^2.6.12" } @@ -579,40 +586,42 @@ } }, "node_modules/esbuild": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", - "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", + "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.20.2", - "@esbuild/android-arm": "0.20.2", - "@esbuild/android-arm64": "0.20.2", - "@esbuild/android-x64": "0.20.2", - "@esbuild/darwin-arm64": "0.20.2", - "@esbuild/darwin-x64": "0.20.2", - "@esbuild/freebsd-arm64": "0.20.2", - "@esbuild/freebsd-x64": "0.20.2", - "@esbuild/linux-arm": "0.20.2", - "@esbuild/linux-arm64": "0.20.2", - "@esbuild/linux-ia32": "0.20.2", - "@esbuild/linux-loong64": "0.20.2", - "@esbuild/linux-mips64el": "0.20.2", - "@esbuild/linux-ppc64": "0.20.2", - "@esbuild/linux-riscv64": "0.20.2", - "@esbuild/linux-s390x": "0.20.2", - "@esbuild/linux-x64": "0.20.2", - "@esbuild/netbsd-x64": "0.20.2", - "@esbuild/openbsd-x64": "0.20.2", - "@esbuild/sunos-x64": "0.20.2", - "@esbuild/win32-arm64": "0.20.2", - "@esbuild/win32-ia32": "0.20.2", - "@esbuild/win32-x64": "0.20.2" + "@esbuild/aix-ppc64": "0.23.1", + "@esbuild/android-arm": "0.23.1", + "@esbuild/android-arm64": "0.23.1", + "@esbuild/android-x64": "0.23.1", + "@esbuild/darwin-arm64": "0.23.1", + "@esbuild/darwin-x64": "0.23.1", + "@esbuild/freebsd-arm64": "0.23.1", + "@esbuild/freebsd-x64": "0.23.1", + "@esbuild/linux-arm": "0.23.1", + "@esbuild/linux-arm64": "0.23.1", + "@esbuild/linux-ia32": "0.23.1", + "@esbuild/linux-loong64": "0.23.1", + "@esbuild/linux-mips64el": "0.23.1", + "@esbuild/linux-ppc64": "0.23.1", + "@esbuild/linux-riscv64": "0.23.1", + "@esbuild/linux-s390x": "0.23.1", + "@esbuild/linux-x64": "0.23.1", + "@esbuild/netbsd-x64": "0.23.1", + "@esbuild/openbsd-arm64": "0.23.1", + "@esbuild/openbsd-x64": "0.23.1", + "@esbuild/sunos-x64": "0.23.1", + "@esbuild/win32-arm64": "0.23.1", + "@esbuild/win32-ia32": "0.23.1", + "@esbuild/win32-x64": "0.23.1" } }, "node_modules/ethereum-bloom-filters": { @@ -710,6 +719,20 @@ "node": ">= 6" } }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -904,6 +927,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "license": "MIT", "peerDependencies": { "ws": "*" } @@ -953,9 +977,10 @@ } }, "node_modules/merkletreejs": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/merkletreejs/-/merkletreejs-0.3.11.tgz", - "integrity": "sha512-LJKTl4iVNTndhL+3Uz/tfkjD0klIWsHlUzgtuNnNrsf7bAlXR30m+xYB7lHr5Z/l6e/yAIsr26Dabx6Buo4VGQ==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/merkletreejs/-/merkletreejs-0.4.0.tgz", + "integrity": "sha512-a48Ta5kWiVNBgeEbZVMm6FB1hBlp6vEuou/XnZdlkmd2zq6NZR6Sh2j+kR1B0iOZIXrTMcigBYzZ39MLdYhm1g==", + "license": "MIT", "dependencies": { "bignumber.js": "^9.0.1", "buffer-reverse": "^1.0.1", @@ -1184,9 +1209,10 @@ } }, "node_modules/solc": { - "version": "0.8.25", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.25.tgz", - "integrity": "sha512-7P0TF8gPeudl1Ko3RGkyY6XVCxe2SdD/qQhtns1vl3yAbK/PDifKDLHGtx1t7mX3LgR7ojV7Fg/Kc6Q9D2T8UQ==", + "version": "0.8.27", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.27.tgz", + "integrity": "sha512-BNxMol2tUAbkH7HKlXBcBqrGi2aqgv+uMHz26mJyTtlVgWmBA4ktiw0qVKHfkjf2oaHbwtbtaSeE2dhn/gTAKw==", + "license": "MIT", "dependencies": { "command-exists": "^1.2.8", "commander": "^8.1.0", @@ -1288,12 +1314,13 @@ } }, "node_modules/tsx": { - "version": "4.10.2", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.10.2.tgz", - "integrity": "sha512-gOfACgv1ElsIjvt7Fp0rMJKGnMGjox0JfGOfX3kmZCV/yZumaNqtHGKBXt1KgaYS9KjDOmqGeI8gHk/W7kWVZg==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.0.tgz", + "integrity": "sha512-bV30kM7bsLZKZIOCHeMNVMJ32/LuJzLVajkQI/qf92J2Qr08ueLQvW00PUZGiuLPP760UINwupgUj8qrSCPUKg==", + "license": "MIT", "dependencies": { - "esbuild": "~0.20.2", - "get-tsconfig": "^4.7.3" + "esbuild": "~0.23.0", + "get-tsconfig": "^4.7.5" }, "bin": { "tsx": "dist/cli.mjs" @@ -1311,21 +1338,23 @@ "integrity": "sha512-+Fy9cqWA/Kv1QX0k6m5ZflGcG2jQSZQGr+jLGXYUM22yihhkHs243LEXvY4cs54lAVyj5gokm0TbgkmL4qDsTg==" }, "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" }, "node_modules/utf8": { "version": "3.0.0", @@ -1350,26 +1379,28 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/web3": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/web3/-/web3-4.8.0.tgz", - "integrity": "sha512-kQSF2NlHk8yjS3SRiJW3S+U5ibkEmVRhB4/GYsVwGvdAkFC2b+EIE1Ob7J56OmqW9VBZgkx1+SuWqo5JTIJSYQ==", - "dependencies": { - "web3-core": "^4.3.2", - "web3-errors": "^1.1.4", - "web3-eth": "^4.6.0", - "web3-eth-abi": "^4.2.1", - "web3-eth-accounts": "^4.1.2", - "web3-eth-contract": "^4.4.0", - "web3-eth-ens": "^4.2.0", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/web3/-/web3-4.12.1.tgz", + "integrity": "sha512-zIFUPdgo2uG5Vbl7C4KrTv8dmWKN3sGnY/GundbiJzcaJZDxaCyu3a5HXAcgUM1VvvsVb1zaUQAFPceq05/q/Q==", + "license": "LGPL-3.0", + "dependencies": { + "web3-core": "^4.5.1", + "web3-errors": "^1.3.0", + "web3-eth": "^4.8.2", + "web3-eth-abi": "^4.2.3", + "web3-eth-accounts": "^4.2.1", + "web3-eth-contract": "^4.7.0", + "web3-eth-ens": "^4.4.0", "web3-eth-iban": "^4.0.7", "web3-eth-personal": "^4.0.8", - "web3-net": "^4.0.7", - "web3-providers-http": "^4.1.0", - "web3-providers-ws": "^4.0.7", - "web3-rpc-methods": "^1.2.0", - "web3-types": "^1.6.0", - "web3-utils": "^4.2.3", - "web3-validator": "^2.0.5" + "web3-net": "^4.1.0", + "web3-providers-http": "^4.2.0", + "web3-providers-ws": "^4.0.8", + "web3-rpc-methods": "^1.3.0", + "web3-rpc-providers": "^1.0.0-rc.2", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.1", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14.0.0", @@ -1377,18 +1408,19 @@ } }, "node_modules/web3-core": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-4.3.2.tgz", - "integrity": "sha512-uIMVd/j4BgOnwfpY8ZT+QKubOyM4xohEhFZXz9xB8wimXWMMlYVlIK/TbfHqFolS9uOerdSGhsMbcK9lETae8g==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-4.5.1.tgz", + "integrity": "sha512-mFMOO/IWdKsLL1o2whh3oJ0LCG9P3l5c4lpiMoVsVln3QXh/B0Gf8gW3aY8S+Ixm0OHyzFDXJVc2CodxqmI4Gw==", + "license": "LGPL-3.0", "dependencies": { - "web3-errors": "^1.1.4", - "web3-eth-accounts": "^4.1.0", + "web3-errors": "^1.3.0", + "web3-eth-accounts": "^4.2.0", "web3-eth-iban": "^4.0.7", - "web3-providers-http": "^4.1.0", - "web3-providers-ws": "^4.0.7", - "web3-types": "^1.3.1", - "web3-utils": "^4.1.0", - "web3-validator": "^2.0.3" + "web3-providers-http": "^4.2.0", + "web3-providers-ws": "^4.0.8", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.1", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -1399,15 +1431,16 @@ } }, "node_modules/web3-core/node_modules/web3-utils": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.2.3.tgz", - "integrity": "sha512-m5plKTC2YtQntHITQRyIePw52UVP1IrShhmA2FACtn4zmc5ADmrXOlQWiPzxFP/18eRJsAaUAw2+CQn1u4WPxQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.1.tgz", + "integrity": "sha512-kGwOk8FxOLJ9DQC68yqNQc7AzN+k9YDLaW+ZjlAXs3qORhf8zXk5SxWAAGLbLykMs3vTeB0FTb1Exut4JEYfFA==", + "license": "LGPL-3.0", "dependencies": { "ethereum-cryptography": "^2.0.0", "eventemitter3": "^5.0.1", - "web3-errors": "^1.1.4", - "web3-types": "^1.6.0", - "web3-validator": "^2.0.5" + "web3-errors": "^1.2.0", + "web3-types": "^1.7.0", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -1415,11 +1448,12 @@ } }, "node_modules/web3-errors": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/web3-errors/-/web3-errors-1.1.4.tgz", - "integrity": "sha512-WahtszSqILez+83AxGecVroyZsMuuRT+KmQp4Si5P4Rnqbczno1k748PCrZTS1J4UCPmXMG2/Vt+0Bz2zwXkwQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/web3-errors/-/web3-errors-1.3.0.tgz", + "integrity": "sha512-j5JkAKCtuVMbY3F5PYXBqg1vWrtF4jcyyMY1rlw8a4PV67AkqlepjGgpzWJZd56Mt+TvHy6DA1F/3Id8LatDSQ==", + "license": "LGPL-3.0", "dependencies": { - "web3-types": "^1.3.1" + "web3-types": "^1.7.0" }, "engines": { "node": ">=14", @@ -1427,21 +1461,22 @@ } }, "node_modules/web3-eth": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-4.6.0.tgz", - "integrity": "sha512-8KtxlGsomovoFULqEpfixgmCpaJ2YIJGxbXUfezh2coXHjVgEopQhARYtKGClyV5kkdCIqwHS8Gvsm6TVNqH6Q==", + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-4.8.2.tgz", + "integrity": "sha512-DLV/fIMG6gBp/B0gv0+G4FzxZ4YCDQsY3lzqqv7avwh3uU7/O27aifCUcFd7Ye+3ixTqCjAvLEl9wYSeyG3zQw==", + "license": "LGPL-3.0", "dependencies": { "setimmediate": "^1.0.5", - "web3-core": "^4.3.2", - "web3-errors": "^1.1.4", - "web3-eth-abi": "^4.2.1", - "web3-eth-accounts": "^4.1.2", - "web3-net": "^4.0.7", - "web3-providers-ws": "^4.0.7", - "web3-rpc-methods": "^1.2.0", - "web3-types": "^1.6.0", - "web3-utils": "^4.2.3", - "web3-validator": "^2.0.5" + "web3-core": "^4.5.0", + "web3-errors": "^1.2.1", + "web3-eth-abi": "^4.2.3", + "web3-eth-accounts": "^4.1.3", + "web3-net": "^4.1.0", + "web3-providers-ws": "^4.0.8", + "web3-rpc-methods": "^1.3.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.1", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -1449,15 +1484,16 @@ } }, "node_modules/web3-eth-abi": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-4.2.1.tgz", - "integrity": "sha512-IE91WUhhiDpBtbkl/DHUoZz7z7T5FXvl3zPLkrxT+dNlOT+wni+US/67jQCLvJRbqf9ApQ26lVYry0bovFgyqA==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-4.2.3.tgz", + "integrity": "sha512-rPVwTn0O1CzbtfXwEfIjUP0W5Y7u1OFjugwKpSqJzPQE6+REBg6OELjomTGZBu+GThxHnv0rp15SOxvqp+tyXA==", + "license": "LGPL-3.0", "dependencies": { "abitype": "0.7.1", - "web3-errors": "^1.1.4", - "web3-types": "^1.6.0", - "web3-utils": "^4.2.3", - "web3-validator": "^2.0.5" + "web3-errors": "^1.2.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.1", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -1465,15 +1501,16 @@ } }, "node_modules/web3-eth-abi/node_modules/web3-utils": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.2.3.tgz", - "integrity": "sha512-m5plKTC2YtQntHITQRyIePw52UVP1IrShhmA2FACtn4zmc5ADmrXOlQWiPzxFP/18eRJsAaUAw2+CQn1u4WPxQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.1.tgz", + "integrity": "sha512-kGwOk8FxOLJ9DQC68yqNQc7AzN+k9YDLaW+ZjlAXs3qORhf8zXk5SxWAAGLbLykMs3vTeB0FTb1Exut4JEYfFA==", + "license": "LGPL-3.0", "dependencies": { "ethereum-cryptography": "^2.0.0", "eventemitter3": "^5.0.1", - "web3-errors": "^1.1.4", - "web3-types": "^1.6.0", - "web3-validator": "^2.0.5" + "web3-errors": "^1.2.0", + "web3-types": "^1.7.0", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -1481,17 +1518,18 @@ } }, "node_modules/web3-eth-accounts": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-4.1.2.tgz", - "integrity": "sha512-y0JynDeTDnclyuE9mShXLeEj+BCrPHxPHOyPCgTchUBQsALF9+0OhP7WiS3IqUuu0Hle5bjG2f5ddeiPtNEuLg==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-4.2.1.tgz", + "integrity": "sha512-aOlEZFzqAgKprKs7+DGArU4r9b+ILBjThpeq42aY7LAQcP+mSpsWcQgbIRK3r/n3OwTYZ3aLPk0Ih70O/LwnYA==", + "license": "LGPL-3.0", "dependencies": { "@ethereumjs/rlp": "^4.0.1", "crc-32": "^1.2.2", "ethereum-cryptography": "^2.0.0", - "web3-errors": "^1.1.4", - "web3-types": "^1.6.0", - "web3-utils": "^4.2.3", - "web3-validator": "^2.0.5" + "web3-errors": "^1.3.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.1", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -1499,15 +1537,16 @@ } }, "node_modules/web3-eth-accounts/node_modules/web3-utils": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.2.3.tgz", - "integrity": "sha512-m5plKTC2YtQntHITQRyIePw52UVP1IrShhmA2FACtn4zmc5ADmrXOlQWiPzxFP/18eRJsAaUAw2+CQn1u4WPxQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.1.tgz", + "integrity": "sha512-kGwOk8FxOLJ9DQC68yqNQc7AzN+k9YDLaW+ZjlAXs3qORhf8zXk5SxWAAGLbLykMs3vTeB0FTb1Exut4JEYfFA==", + "license": "LGPL-3.0", "dependencies": { "ethereum-cryptography": "^2.0.0", "eventemitter3": "^5.0.1", - "web3-errors": "^1.1.4", - "web3-types": "^1.6.0", - "web3-validator": "^2.0.5" + "web3-errors": "^1.2.0", + "web3-types": "^1.7.0", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -1515,33 +1554,48 @@ } }, "node_modules/web3-eth-contract": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-4.4.0.tgz", - "integrity": "sha512-pZ/w6Lb6ZDUUs7f5GCKXiHDAGGvt2tdwiHkvgmQTRnq9b0MEsUpteDyPYspHxKzQWLgbeK37jPb8zbQe4kE/Hg==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-4.7.0.tgz", + "integrity": "sha512-fdStoBOjFyMHwlyJmSUt/BTDL1ATwKGmG3zDXQ/zTKlkkW/F/074ut0Vry4GuwSBg9acMHc0ycOiZx9ZKjNHsw==", + "license": "LGPL-3.0", "dependencies": { - "web3-core": "^4.3.2", - "web3-errors": "^1.1.4", - "web3-eth": "^4.6.0", - "web3-eth-abi": "^4.2.1", - "web3-types": "^1.6.0", - "web3-utils": "^4.2.3", - "web3-validator": "^2.0.5" + "@ethereumjs/rlp": "^5.0.2", + "web3-core": "^4.5.1", + "web3-errors": "^1.3.0", + "web3-eth": "^4.8.2", + "web3-eth-abi": "^4.2.3", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.1", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", "npm": ">=6.12.0" } }, + "node_modules/web3-eth-contract/node_modules/@ethereumjs/rlp": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-5.0.2.tgz", + "integrity": "sha512-DziebCdg4JpGlEqEdGgXmjqcFoJi+JGulUXwEjsZGAscAQ7MyD/7LE/GVCP29vEQxKc7AAwjT3A2ywHp2xfoCA==", + "license": "MPL-2.0", + "bin": { + "rlp": "bin/rlp.cjs" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/web3-eth-contract/node_modules/web3-utils": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.2.3.tgz", - "integrity": "sha512-m5plKTC2YtQntHITQRyIePw52UVP1IrShhmA2FACtn4zmc5ADmrXOlQWiPzxFP/18eRJsAaUAw2+CQn1u4WPxQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.1.tgz", + "integrity": "sha512-kGwOk8FxOLJ9DQC68yqNQc7AzN+k9YDLaW+ZjlAXs3qORhf8zXk5SxWAAGLbLykMs3vTeB0FTb1Exut4JEYfFA==", + "license": "LGPL-3.0", "dependencies": { "ethereum-cryptography": "^2.0.0", "eventemitter3": "^5.0.1", - "web3-errors": "^1.1.4", - "web3-types": "^1.6.0", - "web3-validator": "^2.0.5" + "web3-errors": "^1.2.0", + "web3-types": "^1.7.0", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -1549,19 +1603,20 @@ } }, "node_modules/web3-eth-ens": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-4.2.0.tgz", - "integrity": "sha512-qYj34te2UctoObt8rlEIY/t2MuTMiMiiHhO2JAHRGqSLCQ7b8DM3RpvkiiSB0N0ZyEn+CetZqJCTYb8DNKBS/g==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-4.4.0.tgz", + "integrity": "sha512-DeyVIS060hNV9g8dnTx92syqvgbvPricE3MerCxe/DquNZT3tD8aVgFfq65GATtpCgDDJffO2bVeHp3XBemnSQ==", + "license": "LGPL-3.0", "dependencies": { "@adraffy/ens-normalize": "^1.8.8", - "web3-core": "^4.3.2", - "web3-errors": "^1.1.4", - "web3-eth": "^4.5.0", - "web3-eth-contract": "^4.3.0", - "web3-net": "^4.0.7", - "web3-types": "^1.5.0", - "web3-utils": "^4.2.2", - "web3-validator": "^2.0.5" + "web3-core": "^4.5.0", + "web3-errors": "^1.2.0", + "web3-eth": "^4.8.0", + "web3-eth-contract": "^4.5.0", + "web3-net": "^4.1.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.0", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -1569,15 +1624,16 @@ } }, "node_modules/web3-eth-ens/node_modules/web3-utils": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.2.3.tgz", - "integrity": "sha512-m5plKTC2YtQntHITQRyIePw52UVP1IrShhmA2FACtn4zmc5ADmrXOlQWiPzxFP/18eRJsAaUAw2+CQn1u4WPxQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.1.tgz", + "integrity": "sha512-kGwOk8FxOLJ9DQC68yqNQc7AzN+k9YDLaW+ZjlAXs3qORhf8zXk5SxWAAGLbLykMs3vTeB0FTb1Exut4JEYfFA==", + "license": "LGPL-3.0", "dependencies": { "ethereum-cryptography": "^2.0.0", "eventemitter3": "^5.0.1", - "web3-errors": "^1.1.4", - "web3-types": "^1.6.0", - "web3-validator": "^2.0.5" + "web3-errors": "^1.2.0", + "web3-types": "^1.7.0", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -1649,15 +1705,16 @@ } }, "node_modules/web3-eth/node_modules/web3-utils": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.2.3.tgz", - "integrity": "sha512-m5plKTC2YtQntHITQRyIePw52UVP1IrShhmA2FACtn4zmc5ADmrXOlQWiPzxFP/18eRJsAaUAw2+CQn1u4WPxQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.1.tgz", + "integrity": "sha512-kGwOk8FxOLJ9DQC68yqNQc7AzN+k9YDLaW+ZjlAXs3qORhf8zXk5SxWAAGLbLykMs3vTeB0FTb1Exut4JEYfFA==", + "license": "LGPL-3.0", "dependencies": { "ethereum-cryptography": "^2.0.0", "eventemitter3": "^5.0.1", - "web3-errors": "^1.1.4", - "web3-types": "^1.6.0", - "web3-validator": "^2.0.5" + "web3-errors": "^1.2.0", + "web3-types": "^1.7.0", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -1665,14 +1722,15 @@ } }, "node_modules/web3-net": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-4.0.7.tgz", - "integrity": "sha512-SzEaXFrBjY25iQGk5myaOfO9ZyfTwQEa4l4Ps4HDNVMibgZji3WPzpjq8zomVHMwi8bRp6VV7YS71eEsX7zLow==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-4.1.0.tgz", + "integrity": "sha512-WWmfvHVIXWEoBDWdgKNYKN8rAy6SgluZ0abyRyXOL3ESr7ym7pKWbfP4fjApIHlYTh8tNqkrdPfM4Dyi6CA0SA==", + "license": "LGPL-3.0", "dependencies": { - "web3-core": "^4.3.0", - "web3-rpc-methods": "^1.1.3", - "web3-types": "^1.3.0", - "web3-utils": "^4.0.7" + "web3-core": "^4.4.0", + "web3-rpc-methods": "^1.3.0", + "web3-types": "^1.6.0", + "web3-utils": "^4.3.0" }, "engines": { "node": ">=14", @@ -1680,15 +1738,16 @@ } }, "node_modules/web3-net/node_modules/web3-utils": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.2.3.tgz", - "integrity": "sha512-m5plKTC2YtQntHITQRyIePw52UVP1IrShhmA2FACtn4zmc5ADmrXOlQWiPzxFP/18eRJsAaUAw2+CQn1u4WPxQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.1.tgz", + "integrity": "sha512-kGwOk8FxOLJ9DQC68yqNQc7AzN+k9YDLaW+ZjlAXs3qORhf8zXk5SxWAAGLbLykMs3vTeB0FTb1Exut4JEYfFA==", + "license": "LGPL-3.0", "dependencies": { "ethereum-cryptography": "^2.0.0", "eventemitter3": "^5.0.1", - "web3-errors": "^1.1.4", - "web3-types": "^1.6.0", - "web3-validator": "^2.0.5" + "web3-errors": "^1.2.0", + "web3-types": "^1.7.0", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -1696,14 +1755,15 @@ } }, "node_modules/web3-providers-http": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-4.1.0.tgz", - "integrity": "sha512-6qRUGAhJfVQM41E5t+re5IHYmb5hSaLc02BE2MaRQsz2xKA6RjmHpOA5h/+ojJxEpI9NI2CrfDKOAgtJfoUJQg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-4.2.0.tgz", + "integrity": "sha512-IPMnDtHB7dVwaB7/mMxAZzyq7d5ezfO1+Vw0bNfAeIi7gaDlJiggp85SdyAfOgov8AMUA/dyiY72kQ0KmjXKvQ==", + "license": "LGPL-3.0", "dependencies": { "cross-fetch": "^4.0.0", - "web3-errors": "^1.1.3", - "web3-types": "^1.3.0", - "web3-utils": "^4.0.7" + "web3-errors": "^1.3.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.1" }, "engines": { "node": ">=14", @@ -1711,15 +1771,16 @@ } }, "node_modules/web3-providers-http/node_modules/web3-utils": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.2.3.tgz", - "integrity": "sha512-m5plKTC2YtQntHITQRyIePw52UVP1IrShhmA2FACtn4zmc5ADmrXOlQWiPzxFP/18eRJsAaUAw2+CQn1u4WPxQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.1.tgz", + "integrity": "sha512-kGwOk8FxOLJ9DQC68yqNQc7AzN+k9YDLaW+ZjlAXs3qORhf8zXk5SxWAAGLbLykMs3vTeB0FTb1Exut4JEYfFA==", + "license": "LGPL-3.0", "dependencies": { "ethereum-cryptography": "^2.0.0", "eventemitter3": "^5.0.1", - "web3-errors": "^1.1.4", - "web3-types": "^1.6.0", - "web3-validator": "^2.0.5" + "web3-errors": "^1.2.0", + "web3-types": "^1.7.0", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -1759,16 +1820,17 @@ } }, "node_modules/web3-providers-ws": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-4.0.7.tgz", - "integrity": "sha512-n4Dal9/rQWjS7d6LjyEPM2R458V8blRm0eLJupDEJOOIBhGYlxw5/4FthZZ/cqB7y/sLVi7K09DdYx2MeRtU5w==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-4.0.8.tgz", + "integrity": "sha512-goJdgata7v4pyzHRsg9fSegUG4gVnHZSHODhNnn6J93ykHkBI1nz4fjlGpcQLUMi4jAMz6SHl9Ibzs2jj9xqPw==", + "license": "LGPL-3.0", "dependencies": { "@types/ws": "8.5.3", "isomorphic-ws": "^5.0.0", - "web3-errors": "^1.1.3", - "web3-types": "^1.3.0", - "web3-utils": "^4.0.7", - "ws": "^8.8.1" + "web3-errors": "^1.2.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.1", + "ws": "^8.17.1" }, "engines": { "node": ">=14", @@ -1776,15 +1838,16 @@ } }, "node_modules/web3-providers-ws/node_modules/web3-utils": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.2.3.tgz", - "integrity": "sha512-m5plKTC2YtQntHITQRyIePw52UVP1IrShhmA2FACtn4zmc5ADmrXOlQWiPzxFP/18eRJsAaUAw2+CQn1u4WPxQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.1.tgz", + "integrity": "sha512-kGwOk8FxOLJ9DQC68yqNQc7AzN+k9YDLaW+ZjlAXs3qORhf8zXk5SxWAAGLbLykMs3vTeB0FTb1Exut4JEYfFA==", + "license": "LGPL-3.0", "dependencies": { "ethereum-cryptography": "^2.0.0", "eventemitter3": "^5.0.1", - "web3-errors": "^1.1.4", - "web3-types": "^1.6.0", - "web3-validator": "^2.0.5" + "web3-errors": "^1.2.0", + "web3-types": "^1.7.0", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -1792,13 +1855,49 @@ } }, "node_modules/web3-rpc-methods": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/web3-rpc-methods/-/web3-rpc-methods-1.2.0.tgz", - "integrity": "sha512-CWJ/g4I4WyYvLkf21wCZAehdhU/VjX/OAPHnqF5/FPDJlogOsOnGXHqi1Z5AP+ocdt395PNubd8jyMMJoYGSBA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/web3-rpc-methods/-/web3-rpc-methods-1.3.0.tgz", + "integrity": "sha512-/CHmzGN+IYgdBOme7PdqzF+FNeMleefzqs0LVOduncSaqsppeOEoskLXb2anSpzmQAP3xZJPaTrkQPWSJMORig==", + "license": "LGPL-3.0", + "dependencies": { + "web3-core": "^4.4.0", + "web3-types": "^1.6.0", + "web3-validator": "^2.0.6" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-rpc-providers": { + "version": "1.0.0-rc.2", + "resolved": "https://registry.npmjs.org/web3-rpc-providers/-/web3-rpc-providers-1.0.0-rc.2.tgz", + "integrity": "sha512-ocFIEXcBx/DYQ90HhVepTBUVnL9pGsZw8wyPb1ZINSenwYus9SvcFkjU1Hfvd/fXjuhAv2bUVch9vxvMx1mXAQ==", + "license": "LGPL-3.0", "dependencies": { - "web3-core": "^4.3.2", - "web3-types": "^1.5.0", - "web3-validator": "^2.0.4" + "web3-errors": "^1.3.0", + "web3-providers-http": "^4.2.0", + "web3-providers-ws": "^4.0.8", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.1", + "web3-validator": "^2.0.6" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-rpc-providers/node_modules/web3-utils": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.1.tgz", + "integrity": "sha512-kGwOk8FxOLJ9DQC68yqNQc7AzN+k9YDLaW+ZjlAXs3qORhf8zXk5SxWAAGLbLykMs3vTeB0FTb1Exut4JEYfFA==", + "license": "LGPL-3.0", + "dependencies": { + "ethereum-cryptography": "^2.0.0", + "eventemitter3": "^5.0.1", + "web3-errors": "^1.2.0", + "web3-types": "^1.7.0", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -1806,9 +1905,10 @@ } }, "node_modules/web3-types": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/web3-types/-/web3-types-1.6.0.tgz", - "integrity": "sha512-qgOtADqlD5hw+KPKBUGaXAcdNLL0oh6qTeVgXwewCfbL/lG9R+/GrgMQB1gbTJ3cit8hMwtH8KX2Em6OwO0HRw==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/web3-types/-/web3-types-1.7.0.tgz", + "integrity": "sha512-nhXxDJ7a5FesRw9UG5SZdP/C/3Q2EzHGnB39hkAV+YGXDMgwxBXFWebQLfEzZzuArfHnvC0sQqkIHNwSKcVjdA==", + "license": "LGPL-3.0", "engines": { "node": ">=14", "npm": ">=6.12.0" @@ -1833,14 +1933,15 @@ } }, "node_modules/web3-validator": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/web3-validator/-/web3-validator-2.0.5.tgz", - "integrity": "sha512-2gLOSW8XqEN5pw5jVUm20EB7A8SbQiekpAtiI0JBmCIV0a2rp97v8FgWY5E3UEqnw5WFfEqvcDVW92EyynDTyQ==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/web3-validator/-/web3-validator-2.0.6.tgz", + "integrity": "sha512-qn9id0/l1bWmvH4XfnG/JtGKKwut2Vokl6YXP5Kfg424npysmtRLe9DgiNBM9Op7QL/aSiaA0TVXibuIuWcizg==", + "license": "LGPL-3.0", "dependencies": { "ethereum-cryptography": "^2.0.0", "util": "^0.12.5", - "web3-errors": "^1.1.4", - "web3-types": "^1.5.0", + "web3-errors": "^1.2.0", + "web3-types": "^1.6.0", "zod": "^3.21.4" }, "engines": { @@ -1849,15 +1950,16 @@ } }, "node_modules/web3/node_modules/web3-utils": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.2.3.tgz", - "integrity": "sha512-m5plKTC2YtQntHITQRyIePw52UVP1IrShhmA2FACtn4zmc5ADmrXOlQWiPzxFP/18eRJsAaUAw2+CQn1u4WPxQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.1.tgz", + "integrity": "sha512-kGwOk8FxOLJ9DQC68yqNQc7AzN+k9YDLaW+ZjlAXs3qORhf8zXk5SxWAAGLbLykMs3vTeB0FTb1Exut4JEYfFA==", + "license": "LGPL-3.0", "dependencies": { "ethereum-cryptography": "^2.0.0", "eventemitter3": "^5.0.1", - "web3-errors": "^1.1.4", - "web3-types": "^1.6.0", - "web3-validator": "^2.0.5" + "web3-errors": "^1.2.0", + "web3-types": "^1.7.0", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -1897,15 +1999,16 @@ } }, "node_modules/winston": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.13.0.tgz", - "integrity": "sha512-rwidmA1w3SE4j0E5MuIufFhyJPBDG7Nu71RkZor1p2+qHvJSZ9GYDA81AyleQcZbh/+V6HjeBdfnTZJm9rSeQQ==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.14.2.tgz", + "integrity": "sha512-CO8cdpBB2yqzEf8v895L+GNKYJiEq8eKlHU38af3snQBQ+sdAIUepjMSguOIJC7ICbzm0ZI+Af2If4vIJrtmOg==", + "license": "MIT", "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.2", "async": "^3.2.3", "is-stream": "^2.0.0", - "logform": "^2.4.0", + "logform": "^2.6.0", "one-time": "^1.0.0", "readable-stream": "^3.4.0", "safe-stable-stringify": "^2.3.1", @@ -1931,9 +2034,10 @@ } }, "node_modules/ws": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", - "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "license": "MIT", "engines": { "node": ">=10.0.0" }, diff --git a/local-network/deploy/package.json b/local-network/deploy/package.json index 50c0f055..6dc3d80b 100644 --- a/local-network/deploy/package.json +++ b/local-network/deploy/package.json @@ -6,16 +6,17 @@ "deploy": "npx tsx deploy.ts", "test": "npx tsx test.ts $*" }, + "//dependencies": "npx npm-check-updates -u", "dependencies": { - "@types/node": "^20.12.12", + "@types/node": "^22.5", "@waves/node-api-js": "^1.3.11-beta.1", "@waves/ts-lib-crypto": "^1.4.4-beta.1", - "@waves/waves-transactions": "^4.3.11", - "merkletreejs": "^0.3.11", - "solc": "0.8.25", - "tsx": "^4.10.2", - "typescript": "^4.9.5", - "web3": "^4.7.0", - "winston": "^3.13.0" + "@waves/waves-transactions": "^4.3", + "merkletreejs": "^0.4", + "solc": "0.8.27", + "tsx": "^4.19", + "typescript": "^5.5", + "web3": "^4.12", + "winston": "^3.14" } } diff --git a/local-network/deploy/src/nodes.ts b/local-network/deploy/src/nodes.ts index 6b0a845e..4565caf5 100644 --- a/local-network/deploy/src/nodes.ts +++ b/local-network/deploy/src/nodes.ts @@ -11,7 +11,7 @@ function getWavesApiUrl(insideDocker: boolean, i: number): string { } function getEcApiUrl(insideDocker: boolean, i: number): string { - return insideDocker ? `http://besu-${i}:8545` : `http://127.0.0.1:${i}8545`; + return insideDocker ? `http://ec-${i}:8545` : `http://127.0.0.1:${i}8545`; } function mkWeb3(ecRpcUrl: string): Web3 { diff --git a/local-network/deploy/src/waves-txs.ts b/local-network/deploy/src/waves-txs.ts index e1e33917..62486537 100644 --- a/local-network/deploy/src/waves-txs.ts +++ b/local-network/deploy/src/waves-txs.ts @@ -5,7 +5,7 @@ import * as s from './common-settings'; export const scSetBalances = wt.data( { chainId: s.chainId, - fee: 2400000, + fee: 2_400_000, data: [ { key: `%s__${s.wavesMiner1.address}`, diff --git a/local-network/deploy/src/waves.ts b/local-network/deploy/src/waves.ts index f87867a1..9735bbde 100644 --- a/local-network/deploy/src/waves.ts +++ b/local-network/deploy/src/waves.ts @@ -9,8 +9,9 @@ import * as logger from './logger'; import * as wavesTxs from './waves-txs'; import * as wavesUtils from './waves-utils'; import { ExtendedWavesApi } from './waves-utils'; -import { ec1Rpc } from './nodes'; +import { wavesApi1, wavesApi2, ec1Rpc } from './nodes'; +const wavesApis = [wavesApi1, wavesApi2]; const chainContractAddress = s.chainContract.address; export interface SetupResult { @@ -21,19 +22,9 @@ export interface SetupResult { utils: typeof wavesUtils; } -function getWavesApiUrl(insideDocker: boolean, i: number): string { - return insideDocker ? `http://wavesnode-${i}:6869` : `http://127.0.0.1:${i}6869`; -} - export async function setup(force: boolean): Promise { logger.info('Set up CL'); - const insideDocker = await common.isInsideDocker(); - const wavesApi1Url = getWavesApiUrl(insideDocker, 1); - const wavesApi2Url = getWavesApiUrl(insideDocker, 2); - - logger.info(`Waves Node HTTP API: ${wavesApi1Url}, ${wavesApi2Url}`); - const scSetBalances = async (): Promise => { const tx = wavesTxs.scSetBalances; const dAppAddress = wt.libs.crypto.address({ publicKey: tx.senderPublicKey }, s.chainId); @@ -79,8 +70,8 @@ export async function setup(force: boolean): Promise { if (isContractSetupResponse.result.value) { logger.info('The contract is already set up.'); } else { - const setupTxResult = await wavesApi1.transactions.broadcast(tx); - await wavesUtils.waitForTxn(wavesApi1, setupTxResult.id); + await wavesApi1.transactions.broadcast(tx); + await wavesUtils.waitForTxn(wavesApi1, tx.id); } }; @@ -95,12 +86,18 @@ export async function setup(force: boolean): Promise { } }; - let wavesApi1: ExtendedWavesApi = { ...waves.create(wavesApi1Url), base: wavesApi1Url }; - let wavesApi2: ExtendedWavesApi = { ...waves.create(wavesApi2Url), base: wavesApi2Url }; - logger.info('Wait Waves 1 node'); await wavesUtils.waitForUp(wavesApi1); + logger.info('Wait Waves node has at least one peer'); // Otherwise we can have problems with rollbacks + let connectedPeers = 0; + do { + await common.sleep(2000); + connectedPeers = (await wavesApi1.peers.fetchConnected()).peers.length; + } while (connectedPeers < 1); + + logger.info(`Waves nodes peers: ${connectedPeers}`); + logger.info('Set staking contract balances'); const isNew = await scSetBalances(); const waitTime = 3000;// To eliminate micro fork issue diff --git a/local-network/docker-compose.yml b/local-network/docker-compose.yml index c46159b2..39699668 100644 --- a/local-network/docker-compose.yml +++ b/local-network/docker-compose.yml @@ -2,103 +2,69 @@ name: l2 include: - ./configs/blockscout/${BS-enabled}.yml services: - besu-1: - container_name: besu-1 - hostname: besu-1 - # To update use: docker pull hyperledger/besu:latest - image: hyperledger/besu:latest # Debug version: besu-debug:latest , see _debug/ + ec-1: + container_name: ec-1 + hostname: ec-1 + extends: + file: ./configs/besu/besu.yml + service: besu ports: - - "0.0.0.0:18551:8551" # Engine port - - "0.0.0.0:18545:8545" # RPC port, for Metamask e.g. - - "0.0.0.0:18546:8546" # WebSocket + - "127.0.0.1:18551:8551" # Engine port - doesn't have all APIs + - "127.0.0.1:18545:8545" # RPC port, for Metamask e.g. + - "127.0.0.1:18546:8546" # WebSocket volumes: - - ./logs/besu-1:/opt/besu/logs - - ./configs/besu:/config:ro - environment: - - LOG4J_CONFIGURATION_FILE=/config/log4j2.xml - command: - - '--config-file=/config/besu-1.conf' - - besu-1-check: - container_name: besu-1-check - image: curlimages/curl:8.8.0 - command: > - --retry 20 - --retry-all-errors - --retry-max-time 60 - -d '{"jsonrpc":"2.0","method":"engine_exchangeCapabilities","params":[[]],"id":1}' - http://besu-1:8551 - depends_on: - - besu-1 + - ./configs/ec-common/p2p-key-1.hex:/etc/secrets/p2p-key:ro + - ./logs/ec-1:/opt/besu/logs - besu-2: - container_name: besu-2 - hostname: besu-2 - image: hyperledger/besu:latest + ec-2: + container_name: ec-2 + hostname: ec-2 + extends: + file: ./configs/geth/geth.yml + service: geth ports: - - "0.0.0.0:28551:8551" # Engine port - - "0.0.0.0:28545:8545" # RPC port + - "127.0.0.1:28551:8551" # Engine port + - "127.0.0.1:28545:8545" # RPC port, useful because doesn't require an auth token volumes: - - ./logs/besu-2:/opt/besu/logs - - ./configs/besu:/config:ro - environment: - - LOG4J_CONFIGURATION_FILE=/config/log4j2.xml - command: - - '--config-file=/config/besu-2.conf' - - besu-2-check: - container_name: besu-2-check - image: curlimages/curl:8.8.0 - command: > - --retry 20 - --retry-all-errors - --retry-max-time 60 - -d '{"jsonrpc":"2.0","method":"engine_exchangeCapabilities","params":[[]],"id":1}' - http://besu-2:8551 - depends_on: - - besu-2 + - ./configs/ec-common/p2p-key-2.hex:/etc/secrets/p2p-key:ro + - ./configs/ec-common/jwt-secret-2.hex:/etc/secrets/jwtsecret:ro + - ./logs/ec-2:/root/logs wavesnode-1: container_name: wavesnode-1 hostname: wavesnode-1 + extends: + file: ./configs/wavesnode/wavesnode.yml + service: wavesnode image: unitsnetwork/consensus-client:${WAVES_NODE_1_TAG:-main} - pull_policy: never ports: - - "0.0.0.0:16869:6869" + - "127.0.0.1:16869:6869" environment: - - WAVES_HEAP_SIZE=2g - - JAVA_OPTS=-Dwaves.config.directory=/etc/waves -Dlogback.file.level=TRACE - - NODE_NUMBER=1 + NODE_NUMBER: 1 + WAVES_WALLET_SEED: HnyGuCEnV1A # devnet-1, addr: 3FNraPMYcfuGREcxorNSEBHgNLjmYtaHy9e volumes: - - ./data/wavesnode-1:/var/lib/waves - ./logs/wavesnode-1:/var/log/waves - - ./configs/wavesnode/common:/etc/waves/common:ro - - ./configs/wavesnode/common/logback.xml:/etc/waves/logback.xml:ro - - ./configs/wavesnode/waves-1.conf:/etc/waves/waves.conf:ro depends_on: - besu-1-check: - condition: service_completed_successfully + ec-1: + condition: service_healthy wavesnode-2: container_name: wavesnode-2 hostname: wavesnode-2 + extends: + file: ./configs/wavesnode/wavesnode.yml + service: wavesnode image: unitsnetwork/consensus-client:${WAVES_NODE_2_TAG:-main} - pull_policy: never ports: - - "0.0.0.0:26869:6869" + - "127.0.0.1:26869:6869" environment: - - WAVES_HEAP_SIZE=2g - - JAVA_OPTS=-Dwaves.config.directory=/etc/waves -Dlogback.file.level=TRACE - - NODE_NUMBER=2 + NODE_NUMBER: 2 + WAVES_WALLET_SEED: HnyGuCEnV1B # devnet-2, addr: 3FSrRN8X7cDsLyYTScS8Yf8KSwZgJBwf1jU volumes: - - ./data/wavesnode-2:/var/lib/waves - ./logs/wavesnode-2:/var/log/waves - - ./configs/wavesnode/common:/etc/waves/common:ro - - ./configs/wavesnode/common/logback.xml:/etc/waves/logback.xml:ro - - ./configs/wavesnode/waves-2.conf:/etc/waves/waves.conf:ro depends_on: - besu-2-check: - condition: service_completed_successfully + ec-2: + condition: service_healthy deploy: container_name: deploy @@ -115,6 +81,4 @@ services: - /home/node/app/node_modules # Ignore this subdirectory depends_on: - wavesnode-1 - - wavesnode-2 - - besu-1 - - besu-2 + - ec-1 diff --git a/local-network/genesis-update.sh b/local-network/genesis-update.sh index 25872f6e..abcc8fd6 100755 --- a/local-network/genesis-update.sh +++ b/local-network/genesis-update.sh @@ -18,7 +18,7 @@ else fi java -cp "${DIR}/.cache/waves.jar" com.wavesplatform.GenesisBlockGenerator \ - "${DIR}/configs/wavesnode/common/genesis-template.conf" \ - "${DIR}/configs/wavesnode/common/genesis.conf" > /dev/null + "${DIR}/configs/wavesnode/genesis-template.conf" \ + "${DIR}/configs/wavesnode/genesis.conf" > /dev/null echo "Genesis config updated" diff --git a/src/main/scala/units/Bridge.scala b/src/main/scala/units/Bridge.scala index d040f2f7..5760258c 100644 --- a/src/main/scala/units/Bridge.scala +++ b/src/main/scala/units/Bridge.scala @@ -7,7 +7,7 @@ import com.wavesplatform.utils.EthEncoding import org.web3j.abi.datatypes.Event import org.web3j.abi.datatypes.generated.{Bytes20, Int64} import org.web3j.abi.{FunctionReturnDecoder, TypeEncoder, TypeReference} -import units.client.http.model.GetLogsResponseEntry +import units.client.engine.model.GetLogsResponseEntry import units.eth.Gwei import java.math.BigInteger diff --git a/src/main/scala/units/ConsensusClient.scala b/src/main/scala/units/ConsensusClient.scala index 94c0065d..55d86b46 100644 --- a/src/main/scala/units/ConsensusClient.scala +++ b/src/main/scala/units/ConsensusClient.scala @@ -15,9 +15,8 @@ import monix.execution.{CancelableFuture, Scheduler} import net.ceedubs.ficus.Ficus.* import org.slf4j.LoggerFactory import sttp.client3.HttpClientSyncBackend -import units.client.engine.{EngineApiClient, HttpEngineApiClient} -import units.client.http.{EcApiClient, HttpEcApiClient} -import units.client.{JwtAuthenticationBackend, LoggingBackend} +import units.client.JwtAuthenticationBackend +import units.client.engine.{EngineApiClient, HttpEngineApiClient, LoggedEngineApiClient} import units.network.* import java.util.concurrent.ConcurrentHashMap @@ -28,7 +27,6 @@ class ConsensusClient( config: ClientConfig, context: ExtensionContext, engineApiClient: EngineApiClient, - httpApiClient: EcApiClient, blockObserver: BlocksObserver, allChannels: DefaultChannelGroup, globalScheduler: Scheduler, @@ -42,7 +40,6 @@ class ConsensusClient( deps.config, context, deps.engineApiClient, - deps.httpApiClient, deps.blockObserver, deps.allChannels, deps.globalScheduler, @@ -54,7 +51,6 @@ class ConsensusClient( private[units] val elu = new ELUpdater( - httpApiClient, engineApiClient, context.blockchain, context.utx, @@ -110,7 +106,7 @@ class ConsensusClientDependencies(context: ExtensionContext) extends AutoCloseab val globalScheduler: Scheduler = monix.execution.Scheduler.global val eluScheduler: SchedulerService = Scheduler.singleThread("el-updater", reporter = { e => log.warn("Exception in ELUpdater", e) }) - private val httpClientBackend = new LoggingBackend(HttpClientSyncBackend()) + private val httpClientBackend = HttpClientSyncBackend() private val maybeAuthenticatedBackend = config.jwtSecretFile match { case Some(secretFile) => val src = Source.fromFile(secretFile) @@ -121,15 +117,14 @@ class ConsensusClientDependencies(context: ExtensionContext) extends AutoCloseab httpClientBackend } - val engineApiClient = new HttpEngineApiClient(config, maybeAuthenticatedBackend) - val httpApiClient = new HttpEcApiClient(config, maybeAuthenticatedBackend) + val engineApiClient = new LoggedEngineApiClient(new HttpEngineApiClient(config, maybeAuthenticatedBackend)) val allChannels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE) val peerDatabase = new PeerDatabaseImpl(config.network) val messageObserver = new MessageObserver() private val networkServer = NetworkServer( config, - new HistoryReplier(httpApiClient, engineApiClient)(globalScheduler), + new HistoryReplier(engineApiClient)(globalScheduler), peerDatabase, messageObserver, allChannels, diff --git a/src/main/scala/units/ELUpdater.scala b/src/main/scala/units/ELUpdater.scala index eb98944d..48e64ad6 100644 --- a/src/main/scala/units/ELUpdater.scala +++ b/src/main/scala/units/ELUpdater.scala @@ -33,8 +33,6 @@ import units.client.engine.EngineApiClient import units.client.engine.EngineApiClient.PayloadId import units.client.engine.model.* import units.client.engine.model.Withdrawal.WithdrawalIndex -import units.client.http.EcApiClient -import units.client.http.model.EcBlock import units.eth.{EmptyL2Block, EthAddress, EthereumConstants} import units.network.BlocksObserverImpl.BlockWithChannel import units.util.HexBytesConverter @@ -45,7 +43,6 @@ import scala.concurrent.duration.* import scala.util.* class ELUpdater( - httpApiClient: EcApiClient, engineApiClient: EngineApiClient, blockchain: Blockchain, utx: UtxPool, @@ -265,7 +262,7 @@ class ELUpdater( fixedFinalizedBlock = if (finalizedBlock.height > rollbackBlock.parentBlock.height) rollbackBlock.parentBlock else finalizedBlock _ <- confirmBlock(rollbackBlock.hash, fixedFinalizedBlock.hash) _ <- confirmBlock(target, fixedFinalizedBlock) - lastEcBlock <- httpApiClient.getLastExecutionBlock + lastEcBlock <- engineApiClient.getLastExecutionBlock _ <- Either.cond( targetHash == lastEcBlock.hash, (), @@ -451,14 +448,14 @@ class ELUpdater( else { val finalizedBlock = chainContractClient.getFinalizedBlock logger.debug(s"Finalized block is ${finalizedBlock.hash}") - httpApiClient.getBlockByHash(finalizedBlock.hash) match { + engineApiClient.getBlockByHash(finalizedBlock.hash) match { case Left(error) => logger.error(s"Could not load finalized block", error) case Right(Some(finalizedEcBlock)) => logger.trace(s"Finalized block ${finalizedBlock.hash} is at height ${finalizedEcBlock.height}") (for { newEpochInfo <- calculateEpochInfo mainChainInfo <- chainContractClient.getMainChainInfo.toRight("Can't get main chain info") - lastEcBlock <- httpApiClient.getLastExecutionBlock.leftMap(_.message) + lastEcBlock <- engineApiClient.getLastExecutionBlock.leftMap(_.message) } yield { logger.trace(s"Following main chain ${mainChainInfo.id}") val fullValidationStatus = FullValidationStatus( @@ -620,7 +617,7 @@ class ELUpdater( val finalizedBlock = chainContractClient.getFinalizedBlock val options = chainContractClient.getOptions logger.debug(s"Finalized block is ${finalizedBlock.hash}") - httpApiClient.getBlockByHash(finalizedBlock.hash) match { + engineApiClient.getBlockByHash(finalizedBlock.hash) match { case Left(error) => logger.error(s"Could not load finalized block", error) case Right(Some(finalizedEcBlock)) => logger.trace(s"Finalized block ${finalizedBlock.hash} is at height ${finalizedEcBlock.height}") @@ -722,7 +719,7 @@ class ELUpdater( private def requestBlock(hash: BlockHash): BlockRequestResult = { logger.debug(s"Requesting block $hash") - httpApiClient.getBlockByHash(hash) match { + engineApiClient.getBlockByHash(hash) match { case Right(Some(block)) => BlockRequestResult.BlockExists(block) case Right(None) => requestAndProcessBlock(hash) @@ -788,7 +785,7 @@ class ELUpdater( ): Option[Working[FollowingChain]] = { @tailrec def findLastEcBlock(curBlock: ContractBlock): EcBlock = { - httpApiClient.getBlockByHash(curBlock.hash) match { + engineApiClient.getBlockByHash(curBlock.hash) match { case Right(Some(block)) => block case Right(_) => chainContractClient.getBlock(curBlock.parentHash) match { @@ -877,7 +874,7 @@ class ELUpdater( private def waitForSyncCompletion(target: ContractBlock): Unit = scheduler.scheduleOnce(5.seconds)(state match { case SyncingToFinalizedBlock(finalizedBlockHash) if finalizedBlockHash == target.hash => logger.debug(s"Checking if EL has synced to ${target.hash} on height ${target.height}") - httpApiClient.getLastExecutionBlock match { + engineApiClient.getLastExecutionBlock match { case Left(error) => logger.error(s"Sync to ${target.hash} was not completed, error=${error.message}") setState("23", Starting) @@ -1209,11 +1206,11 @@ class ELUpdater( private def mkRollbackBlock(rollbackTargetBlockId: BlockHash): Job[RollbackBlock] = for { targetBlockFromContract <- Right(chainContractClient.getBlock(rollbackTargetBlockId)) targetBlockOpt <- targetBlockFromContract match { - case None => httpApiClient.getBlockByHash(rollbackTargetBlockId) + case None => engineApiClient.getBlockByHash(rollbackTargetBlockId) case x => Right(x) } targetBlock <- Either.fromOption(targetBlockOpt, ClientError(s"Can't find block $rollbackTargetBlockId neither on a contract, nor in EC")) - parentBlock <- httpApiClient.getBlockByHash(targetBlock.parentHash) + parentBlock <- engineApiClient.getBlockByHash(targetBlock.parentHash) parentBlock <- Either.fromOption(parentBlock, ClientError(s"Can't find parent block $rollbackTargetBlockId in execution client")) rollbackBlockOpt <- engineApiClient.applyNewPayload(EmptyL2Block.mkExecutionPayload(parentBlock)) rollbackBlock <- Either.fromOption(rollbackBlockOpt, ClientError("Rollback block hash is not defined as latest valid hash")) @@ -1226,7 +1223,7 @@ class ELUpdater( } private def getLastWithdrawalIndex(hash: BlockHash): Job[WithdrawalIndex] = - httpApiClient.getBlockByHash(hash).flatMap { + engineApiClient.getBlockByHash(hash).flatMap { case None => Left(ClientError(s"Can't find $hash block on EC during withdrawal search")) case Some(ecBlock) => ecBlock.withdrawals.lastOption match { @@ -1239,7 +1236,7 @@ class ELUpdater( private def getElToClTransfersRootHash(hash: BlockHash, elBridgeAddress: EthAddress): Job[Digest] = for { - elRawLogs <- httpApiClient.getLogs(hash, Bridge.ElSentNativeEventTopic) + elRawLogs <- engineApiClient.getLogs(hash, elBridgeAddress, Bridge.ElSentNativeEventTopic) rootHash <- { val relatedElRawLogs = elRawLogs.filter(x => x.address == elBridgeAddress && x.topics.contains(Bridge.ElSentNativeEventTopic)) Bridge @@ -1413,7 +1410,7 @@ class ELUpdater( if (fullValidationStatus.validated.contains(lastContractBlock.hash)) Right(BlockForValidation.NotFound) else if (lastContractBlock.height <= finalizedBlock.height) Right(BlockForValidation.SkippedFinalized(lastContractBlock)) else - httpApiClient + engineApiClient .getBlockByHash(lastContractBlock.hash) .map { case Some(ecBlock) => BlockForValidation.Found(lastContractBlock, ecBlock) diff --git a/src/main/scala/units/NetworkL2Block.scala b/src/main/scala/units/NetworkL2Block.scala index c8ae1a9c..3e6cdf45 100644 --- a/src/main/scala/units/NetworkL2Block.scala +++ b/src/main/scala/units/NetworkL2Block.scala @@ -5,13 +5,12 @@ import com.wavesplatform.account.PrivateKey import com.wavesplatform.common.state.ByteStr import com.wavesplatform.crypto import com.wavesplatform.crypto.{DigestLength, SignatureLength} +import org.web3j.abi.datatypes.generated.Uint256 +import play.api.libs.json.{JsObject, Json} import units.client.L2BlockLike -import units.client.engine.model.Withdrawal -import units.client.http.model.EcBlock +import units.client.engine.model.{EcBlock, Withdrawal} import units.eth.EthAddress import units.util.HexBytesConverter.* -import org.web3j.abi.datatypes.generated.Uint256 -import play.api.libs.json.{JsObject, Json} // TODO Refactor to eliminate a manual deserialization, e.g. (raw: JsonObject, parsed: ParsedBlockL2) class NetworkL2Block private ( diff --git a/src/main/scala/units/client/LoggingBackend.scala b/src/main/scala/units/client/LoggingBackend.scala deleted file mode 100644 index d720a3f2..00000000 --- a/src/main/scala/units/client/LoggingBackend.scala +++ /dev/null @@ -1,27 +0,0 @@ -package units.client - -import com.wavesplatform.utils.ScorexLogging -import sttp.capabilities.Effect -import sttp.client3.* - -class LoggingBackend[F[_], P](delegate: SttpBackend[F, P]) extends DelegateSttpBackend[F, P](delegate) with ScorexLogging { - override def send[T, R >: P & Effect[F]](request: Request[T, R]): F[Response[T]] = { - val prefix = request.tag(RequestIdTag).fold("")(id => s"[$id] ") - val requestWithRawJson = request.response(asBothOption(request.response, asStringAlways)) - - log.trace(request.tag(RetriesLeftTag) match { - case Some(retriesLeft) => s"${prefix}Retry, retries left: $retriesLeft" - case None => s"${prefix}Request: ${request.uri}, body=${request.body.show}" - }) - - val withErrorLog = responseMonad.handleError(requestWithRawJson.send(delegate)) { x => - log.trace(s"$prefix${x.getMessage}", x) - responseMonad.error(x) - } - - responseMonad.flatMap(withErrorLog) { response => - log.trace(s"${prefix}Response: ${response.code}, body=${response.body._2.getOrElse("empty")}") - responseMonad.unit(response.copy(body = response.body._1)) - } - } -} diff --git a/src/main/scala/units/client/contract/ChainContractSnapshotClient.scala b/src/main/scala/units/client/contract/ChainContractSnapshotClient.scala deleted file mode 100644 index be643b3a..00000000 --- a/src/main/scala/units/client/contract/ChainContractSnapshotClient.scala +++ /dev/null @@ -1,29 +0,0 @@ -package units.client.contract - -import cats.kernel.Monoid -import com.wavesplatform.account.Address -import com.wavesplatform.api.http.StateSnapshotJson -import com.wavesplatform.state.{DataEntry, NewTransactionInfo, StateSnapshot, TxMeta} -import com.wavesplatform.transaction.smart.InvokeScriptTransaction -import com.wavesplatform.utils.ScorexLogging -import play.api.libs.json.Json - -class ChainContractSnapshotClient(val contract: Address, snapshot: StateSnapshot) extends ChainContractClient with ScorexLogging { - - private val totalSnapshot: StateSnapshot = - Monoid[StateSnapshot].combineAll(snapshot +: snapshot.transactions.values.toSeq.map(_.snapshot)) - - def logDataChanges(): Unit = if (totalSnapshot.accountData.nonEmpty) { - snapshot.transactions.foreach { - case (id, txInfo @ NewTransactionInfo(tx: InvokeScriptTransaction, txSnapshot, _, TxMeta.Status.Succeeded, _)) - if tx.dApp == contract && txSnapshot.accountData.nonEmpty => // Don't resolve a possible alias, because it is only for logs - val dataJson = Json.toJson(StateSnapshotJson.fromSnapshot(txSnapshot, txInfo.status).accountData) - log.trace(s"[$id] Data changes: $dataJson") - - case _ => - } - } - - override def extractData(key: String): Option[DataEntry[?]] = - totalSnapshot.accountData.get(contract).flatMap(_.get(key)) -} diff --git a/src/main/scala/units/client/contract/ContractBlock.scala b/src/main/scala/units/client/contract/ContractBlock.scala index 6299fdcd..a1ea7858 100644 --- a/src/main/scala/units/client/contract/ContractBlock.scala +++ b/src/main/scala/units/client/contract/ContractBlock.scala @@ -5,6 +5,7 @@ import com.wavesplatform.common.state.ByteStr import units.BlockHash import units.client.L2BlockLike import units.eth.EthAddress +import units.util.HexBytesConverter.toHex case class ContractBlock( hash: BlockHash, @@ -16,7 +17,11 @@ case class ContractBlock( chainId: Long, elToClTransfersRootHash: Digest, lastClToElTransferIndex: Long -) extends L2BlockLike +) extends L2BlockLike { + override def toString: String = + s"ContractBlock($hash, p=$parentHash, e=$epoch, h=$height, m=$minerRewardL2Address ($generator), c=$chainId, " + + s"e2c=${if (elToClTransfersRootHash.isEmpty) "" else toHex(elToClTransfersRootHash)}, c2e=$lastClToElTransferIndex)" +} object ContractBlock { val ElToClTransfersRootHashLength = 32 // bytes diff --git a/src/main/scala/units/client/engine/EngineApiClient.scala b/src/main/scala/units/client/engine/EngineApiClient.scala index 25444b9d..200b7e4e 100644 --- a/src/main/scala/units/client/engine/EngineApiClient.scala +++ b/src/main/scala/units/client/engine/EngineApiClient.scala @@ -1,13 +1,12 @@ package units.client.engine +import play.api.libs.json.* import units.client.engine.EngineApiClient.PayloadId import units.client.engine.model.* import units.eth.EthAddress import units.{BlockHash, Job} -import play.api.libs.json.* trait EngineApiClient { - def forkChoiceUpdate(blockHash: BlockHash, finalizedBlockHash: BlockHash): Job[String] // TODO Replace String with an appropriate type def forkChoiceUpdateWithPayloadId( @@ -24,6 +23,18 @@ trait EngineApiClient { def applyNewPayload(payload: JsObject): Job[Option[BlockHash]] def getPayloadBodyByHash(hash: BlockHash): Job[Option[JsObject]] + + def getBlockByNumber(number: BlockNumber): Job[Option[EcBlock]] + + def getBlockByHash(hash: BlockHash): Job[Option[EcBlock]] + + def getBlockByHashJson(hash: BlockHash): Job[Option[JsObject]] + + def getLastExecutionBlock: Job[EcBlock] + + def blockExists(hash: BlockHash): Job[Boolean] + + def getLogs(hash: BlockHash, address: EthAddress, topic: String): Job[List[GetLogsResponseEntry]] } object EngineApiClient { diff --git a/src/main/scala/units/client/engine/HttpEngineApiClient.scala b/src/main/scala/units/client/engine/HttpEngineApiClient.scala index 27bf8871..810af2a7 100644 --- a/src/main/scala/units/client/engine/HttpEngineApiClient.scala +++ b/src/main/scala/units/client/engine/HttpEngineApiClient.scala @@ -1,5 +1,10 @@ package units.client.engine +import cats.syntax.either.* +import cats.syntax.traverse.* +import play.api.libs.json.* +import sttp.client3.* +import sttp.model.Uri import units.client.JsonRpcClient import units.client.engine.EngineApiClient.PayloadId import units.client.engine.HttpEngineApiClient.* @@ -7,9 +12,6 @@ import units.client.engine.model.* import units.client.engine.model.ForkChoiceUpdatedRequest.ForkChoiceAttributes import units.eth.EthAddress import units.{BlockHash, ClientConfig, ClientError, Job} -import play.api.libs.json.* -import sttp.client3.* -import sttp.model.Uri import scala.concurrent.duration.{DurationInt, FiniteDuration} @@ -18,7 +20,10 @@ class HttpEngineApiClient(val config: ClientConfig, val backend: SttpBackend[Ide val apiUrl: Uri = uri"${config.executionClientAddress}" def forkChoiceUpdate(blockHash: BlockHash, finalizedBlockHash: BlockHash): Job[String] = { - sendEngineRequest[ForkChoiceUpdatedRequest, ForkChoiceUpdatedResponse](ForkChoiceUpdatedRequest(blockHash, finalizedBlockHash, None), BlockExecutionTimeout) + sendEngineRequest[ForkChoiceUpdatedRequest, ForkChoiceUpdatedResponse]( + ForkChoiceUpdatedRequest(blockHash, finalizedBlockHash, None), + BlockExecutionTimeout + ) .flatMap { case ForkChoiceUpdatedResponse(PayloadStatus(status, _, _), None) if status == "SYNCING" || status == "VALID" => Right(status) case ForkChoiceUpdatedResponse(PayloadStatus(_, _, Some(validationError)), _) => @@ -73,6 +78,41 @@ class HttpEngineApiClient(val config: ClientConfig, val backend: SttpBackend[Ide .map(_.value.headOption.flatMap(_.asOpt[JsObject])) } + def getBlockByNumber(number: BlockNumber): Job[Option[EcBlock]] = { + for { + json <- getBlockByNumberJson(number.str) + blockMeta <- json.traverse(parseJson[EcBlock](_)) + } yield blockMeta + } + + def getBlockByHash(hash: BlockHash): Job[Option[EcBlock]] = { + sendRequest[GetBlockByHashRequest, EcBlock](GetBlockByHashRequest(hash)) + .leftMap(err => ClientError(s"Error getting block by hash $hash: $err")) + } + + def getBlockByHashJson(hash: BlockHash): Job[Option[JsObject]] = { + sendRequest[GetBlockByHashRequest, JsObject](GetBlockByHashRequest(hash)) + .leftMap(err => ClientError(s"Error getting block json by hash $hash: $err")) + } + + def getLastExecutionBlock: Job[EcBlock] = for { + lastEcBlockOpt <- getBlockByNumber(BlockNumber.Latest) + lastEcBlock <- Either.fromOption(lastEcBlockOpt, ClientError("Impossible: EC doesn't have blocks")) + } yield lastEcBlock + + def blockExists(hash: BlockHash): Job[Boolean] = + getBlockByHash(hash).map(_.isDefined) + + private def getBlockByNumberJson(number: String): Job[Option[JsObject]] = { + sendRequest[GetBlockByNumberRequest, JsObject](GetBlockByNumberRequest(number)) + .leftMap(err => ClientError(s"Error getting block by number $number: $err")) + } + + override def getLogs(hash: BlockHash, address: EthAddress, topic: String): Job[List[GetLogsResponseEntry]] = + sendRequest[GetLogsRequest, List[GetLogsResponseEntry]](GetLogsRequest(hash, address, List(topic))) + .leftMap(err => ClientError(s"Error getting block logs by hash $hash: $err")) + .map(_.getOrElse(List.empty)) + private def sendEngineRequest[A: Writes, B: Reads](request: A, timeout: FiniteDuration): Job[B] = { sendRequest(request, timeout) match { case Right(response) => response.toRight(ClientError(s"Unexpected engine API empty response")) diff --git a/src/main/scala/units/client/engine/LoggedEngineApiClient.scala b/src/main/scala/units/client/engine/LoggedEngineApiClient.scala new file mode 100644 index 00000000..0a183309 --- /dev/null +++ b/src/main/scala/units/client/engine/LoggedEngineApiClient.scala @@ -0,0 +1,79 @@ +package units.client.engine + +import com.wavesplatform.utils.LoggerFacade +import org.slf4j.LoggerFactory +import play.api.libs.json.JsObject +import units.client.engine.EngineApiClient.PayloadId +import units.client.engine.LoggedEngineApiClient.excludedJsonFields +import units.client.engine.model.* +import units.eth.EthAddress +import units.{BlockHash, Job} + +import java.util.concurrent.ThreadLocalRandom +import scala.util.chaining.scalaUtilChainingOps + +class LoggedEngineApiClient(underlying: EngineApiClient) extends EngineApiClient { + protected val log = LoggerFacade(LoggerFactory.getLogger(underlying.getClass)) + + override def forkChoiceUpdate(blockHash: BlockHash, finalizedBlockHash: BlockHash): Job[String] = + wrap(s"forkChoiceUpdate($blockHash, f=$finalizedBlockHash)", underlying.forkChoiceUpdate(blockHash, finalizedBlockHash)) + + override def forkChoiceUpdateWithPayloadId( + lastBlockHash: BlockHash, + finalizedBlockHash: BlockHash, + unixEpochSeconds: Long, + suggestedFeeRecipient: EthAddress, + prevRandao: String, + withdrawals: Vector[Withdrawal] + ): Job[PayloadId] = wrap( + s"forkChoiceUpdateWithPayloadId(l=$lastBlockHash, f=$finalizedBlockHash, ts=$unixEpochSeconds, m=$suggestedFeeRecipient, " + + s"r=$prevRandao, w={${withdrawals.mkString(", ")}}", + underlying.forkChoiceUpdateWithPayloadId(lastBlockHash, finalizedBlockHash, unixEpochSeconds, suggestedFeeRecipient, prevRandao, withdrawals) + ) + + override def getPayload(payloadId: PayloadId): Job[JsObject] = + wrap(s"getPayload($payloadId)", underlying.getPayload(payloadId), filteredJson) + + override def applyNewPayload(payload: JsObject): Job[Option[BlockHash]] = + wrap(s"applyNewPayload(${filteredJson(payload)})", underlying.applyNewPayload(payload), _.fold("None")(_.toString)) + + override def getPayloadBodyByHash(hash: BlockHash): Job[Option[JsObject]] = + wrap(s"getPayloadBodyByHash($hash)", underlying.getPayloadBodyByHash(hash), _.fold("None")(filteredJson)) + + override def getBlockByNumber(number: BlockNumber): Job[Option[EcBlock]] = + wrap(s"getBlockByNumber($number)", underlying.getBlockByNumber(number), _.fold("None")(_.toString)) + + override def getBlockByHash(hash: BlockHash): Job[Option[EcBlock]] = + wrap(s"getBlockByHash($hash)", underlying.getBlockByHash(hash), _.fold("None")(_.toString)) + + override def getBlockByHashJson(hash: BlockHash): Job[Option[JsObject]] = + wrap(s"getBlockByHashJson($hash)", underlying.getBlockByHashJson(hash), _.fold("None")(filteredJson)) + + override def getLastExecutionBlock: Job[EcBlock] = + wrap("getLastExecutionBlock", underlying.getLastExecutionBlock) + + override def blockExists(hash: BlockHash): Job[Boolean] = + wrap(s"blockExists($hash)", underlying.blockExists(hash)) + + override def getLogs(hash: BlockHash, address: EthAddress, topic: String): Job[List[GetLogsResponseEntry]] = + wrap(s"getLogs($hash, a=$address, t=$topic)", underlying.getLogs(hash, address, topic), _.view.map(_.data).mkString("{", ", ", "}")) + + protected def wrap[R](method: String, f: => Job[R], toMsg: R => String = (_: R).toString): Job[R] = { + val currRequestId = ThreadLocalRandom.current().nextInt(10000, 100000).toString + log.debug(s"[$currRequestId] $method") + + f.tap { + case Left(e) => log.debug(s"[$currRequestId] Error: ${e.message}") + case Right(r) => log.debug(s"[$currRequestId] Success: ${toMsg(r)}") + } + } + + private def filteredJson(jsObject: JsObject): String = JsObject( + jsObject.fields.filterNot { case (k, _) => excludedJsonFields.contains(k) } + ).toString() +} + +object LoggedEngineApiClient { + private val excludedJsonFields = + Set("transactions", "logsBloom", "stateRoot", "gasLimit", "gasUsed", "baseFeePerGas", "excessBlobGas") +} diff --git a/src/main/scala/units/client/http/model/BlockNumber.scala b/src/main/scala/units/client/engine/model/BlockNumber.scala similarity index 87% rename from src/main/scala/units/client/http/model/BlockNumber.scala rename to src/main/scala/units/client/engine/model/BlockNumber.scala index aba476cb..d70c603e 100644 --- a/src/main/scala/units/client/http/model/BlockNumber.scala +++ b/src/main/scala/units/client/engine/model/BlockNumber.scala @@ -1,4 +1,4 @@ -package units.client.http.model +package units.client.engine.model import units.util.HexBytesConverter diff --git a/src/main/scala/units/client/http/model/EcBlock.scala b/src/main/scala/units/client/engine/model/EcBlock.scala similarity index 87% rename from src/main/scala/units/client/http/model/EcBlock.scala rename to src/main/scala/units/client/engine/model/EcBlock.scala index fff78809..587e87b3 100644 --- a/src/main/scala/units/client/http/model/EcBlock.scala +++ b/src/main/scala/units/client/engine/model/EcBlock.scala @@ -1,14 +1,13 @@ -package units.client.http.model +package units.client.engine.model -import units.BlockHash -import units.client.L2BlockLike -import units.client.engine.model.Withdrawal -import units.eth.EthAddress -import units.util.HexBytesConverter.* import org.web3j.abi.datatypes.generated.Uint256 import play.api.libs.functional.syntax.* import play.api.libs.json.* import play.api.libs.json.Format.GenericFormat +import units.BlockHash +import units.client.L2BlockLike +import units.eth.EthAddress +import units.util.HexBytesConverter.* /** Block in EC API, not a payload of Engine API! See BlockHeader in besu. * @param timestamp @@ -26,7 +25,10 @@ case class EcBlock( gasLimit: Long, gasUsed: Long, withdrawals: Vector[Withdrawal] -) extends L2BlockLike +) extends L2BlockLike { + override def toString: String = + s"EcBlock($hash, p=$parentHash, h=$height, t=$timestamp, m=$minerRewardL2Address, w={${withdrawals.mkString(", ")}})" +} object EcBlock { implicit val reads: Reads[EcBlock] = ( diff --git a/src/main/scala/units/client/http/model/GetBlockByHashRequest.scala b/src/main/scala/units/client/engine/model/GetBlockByHashRequest.scala similarity index 66% rename from src/main/scala/units/client/http/model/GetBlockByHashRequest.scala rename to src/main/scala/units/client/engine/model/GetBlockByHashRequest.scala index 236a385d..c341e4ba 100644 --- a/src/main/scala/units/client/http/model/GetBlockByHashRequest.scala +++ b/src/main/scala/units/client/engine/model/GetBlockByHashRequest.scala @@ -1,15 +1,15 @@ -package units.client.http.model +package units.client.engine.model -import units.BlockHash import play.api.libs.json.{Json, Writes} +import units.BlockHash -case class GetBlockByHashRequest(hash: BlockHash, fullTxs: Boolean) +case class GetBlockByHashRequest(hash: BlockHash) object GetBlockByHashRequest { implicit val writes: Writes[GetBlockByHashRequest] = (o: GetBlockByHashRequest) => { Json.obj( "jsonrpc" -> "2.0", "method" -> "eth_getBlockByHash", - "params" -> Json.arr(o.hash, o.fullTxs), + "params" -> Json.arr(o.hash, false), "id" -> 1 ) } diff --git a/src/main/scala/units/client/http/model/GetBlockByNumberRequest.scala b/src/main/scala/units/client/engine/model/GetBlockByNumberRequest.scala similarity index 91% rename from src/main/scala/units/client/http/model/GetBlockByNumberRequest.scala rename to src/main/scala/units/client/engine/model/GetBlockByNumberRequest.scala index 5be68cc9..f3fedd61 100644 --- a/src/main/scala/units/client/http/model/GetBlockByNumberRequest.scala +++ b/src/main/scala/units/client/engine/model/GetBlockByNumberRequest.scala @@ -1,4 +1,4 @@ -package units.client.http.model +package units.client.engine.model import play.api.libs.json.{Json, Writes} diff --git a/src/main/scala/units/client/http/model/GetLogsRequest.scala b/src/main/scala/units/client/engine/model/GetLogsRequest.scala similarity index 75% rename from src/main/scala/units/client/http/model/GetLogsRequest.scala rename to src/main/scala/units/client/engine/model/GetLogsRequest.scala index f10461a3..1d7fc759 100644 --- a/src/main/scala/units/client/http/model/GetLogsRequest.scala +++ b/src/main/scala/units/client/engine/model/GetLogsRequest.scala @@ -1,14 +1,15 @@ -package units.client.http.model +package units.client.engine.model import units.BlockHash import play.api.libs.json.{Json, Writes} +import units.eth.EthAddress /** @param topics * Event signature hash and indexed event parameters * @see * https://besu.hyperledger.org/stable/public-networks/reference/api#eth_getlogs */ -case class GetLogsRequest(hash: BlockHash, topics: List[String]) +case class GetLogsRequest(hash: BlockHash, address: EthAddress, topics: List[String]) object GetLogsRequest { implicit val writes: Writes[GetLogsRequest] = (o: GetLogsRequest) => { Json.obj( @@ -17,6 +18,7 @@ object GetLogsRequest { "params" -> Json.arr( Json.obj( "blockHash" -> o.hash, + "address" -> o.address, "topics" -> o.topics ) ), diff --git a/src/main/scala/units/client/http/model/GetLogsResponseEntry.scala b/src/main/scala/units/client/engine/model/GetLogsResponseEntry.scala similarity index 91% rename from src/main/scala/units/client/http/model/GetLogsResponseEntry.scala rename to src/main/scala/units/client/engine/model/GetLogsResponseEntry.scala index 03c04041..0cc0290d 100644 --- a/src/main/scala/units/client/http/model/GetLogsResponseEntry.scala +++ b/src/main/scala/units/client/engine/model/GetLogsResponseEntry.scala @@ -1,7 +1,7 @@ -package units.client.http.model +package units.client.engine.model -import units.eth.EthAddress import play.api.libs.json.{Json, Reads} +import units.eth.EthAddress /** @param topics * List of hex values diff --git a/src/main/scala/units/client/http/EcApiClient.scala b/src/main/scala/units/client/http/EcApiClient.scala deleted file mode 100644 index 0ef612bd..00000000 --- a/src/main/scala/units/client/http/EcApiClient.scala +++ /dev/null @@ -1,19 +0,0 @@ -package units.client.http - -import units.client.http.model.* -import units.{BlockHash, Job} -import play.api.libs.json.JsObject - -trait EcApiClient { - def getBlockByNumber(number: BlockNumber): Job[Option[EcBlock]] - - def getBlockByHash(hash: BlockHash): Job[Option[EcBlock]] - - def getBlockByHashJson(hash: BlockHash, fullTxs: Boolean = false): Job[Option[JsObject]] - - def getLastExecutionBlock: Job[EcBlock] - - def blockExists(hash: BlockHash): Job[Boolean] - - def getLogs(hash: BlockHash, topic: String): Job[List[GetLogsResponseEntry]] -} diff --git a/src/main/scala/units/client/http/HttpEcApiClient.scala b/src/main/scala/units/client/http/HttpEcApiClient.scala deleted file mode 100644 index 0c1674cd..00000000 --- a/src/main/scala/units/client/http/HttpEcApiClient.scala +++ /dev/null @@ -1,48 +0,0 @@ -package units.client.http - -import cats.syntax.either.* -import cats.syntax.traverse.* -import units.client.JsonRpcClient -import units.client.http.model.* -import units.{BlockHash, ClientConfig, ClientError, Job} -import play.api.libs.json.JsObject -import sttp.client3.* - -class HttpEcApiClient(val config: ClientConfig, val backend: SttpBackend[Identity, ?]) extends EcApiClient with JsonRpcClient { - - val apiUrl = uri"${config.executionClientAddress}" - - def getBlockByNumber(number: BlockNumber): Job[Option[EcBlock]] = { - for { - json <- getBlockByNumberJson(number.str) - blockMeta <- json.traverse(parseJson[EcBlock](_)) - } yield blockMeta - } - - def getBlockByHash(hash: BlockHash): Job[Option[EcBlock]] = { - sendRequest[GetBlockByHashRequest, EcBlock](GetBlockByHashRequest(hash, fullTxs = false)) - .leftMap(err => ClientError(s"Error getting block by hash $hash: $err")) - } - - def getBlockByHashJson(hash: BlockHash, fullTxs: Boolean = false): Job[Option[JsObject]] = { - sendRequest[GetBlockByHashRequest, JsObject](GetBlockByHashRequest(hash, fullTxs)) - .leftMap(err => ClientError(s"Error getting block json by hash $hash: $err")) - } - - def getLastExecutionBlock: Job[EcBlock] = for { - lastEcBlockOpt <- getBlockByNumber(BlockNumber.Latest) - lastEcBlock <- Either.fromOption(lastEcBlockOpt, ClientError("Impossible: EC doesn't have blocks")) - } yield lastEcBlock - - def blockExists(hash: BlockHash): Job[Boolean] = - getBlockByHash(hash).map(_.isDefined) - - private def getBlockByNumberJson(number: String): Job[Option[JsObject]] = { - sendRequest[GetBlockByNumberRequest, JsObject](GetBlockByNumberRequest(number)) - .leftMap(err => ClientError(s"Error getting block by number $number: $err")) - } - override def getLogs(hash: BlockHash, topic: String): Job[List[GetLogsResponseEntry]] = - sendRequest[GetLogsRequest, List[GetLogsResponseEntry]](GetLogsRequest(hash, List(topic))) - .leftMap(err => ClientError(s"Error getting block logs by hash $hash: $err")) - .map(_.getOrElse(List.empty)) -} diff --git a/src/main/scala/units/eth/EmptyL2Block.scala b/src/main/scala/units/eth/EmptyL2Block.scala index dcdee6e4..f0165c66 100644 --- a/src/main/scala/units/eth/EmptyL2Block.scala +++ b/src/main/scala/units/eth/EmptyL2Block.scala @@ -1,11 +1,11 @@ package units.eth -import units.BlockHash -import units.client.http.model.EcBlock -import units.util.HexBytesConverter import org.web3j.abi.datatypes.generated.Uint256 import org.web3j.rlp.{RlpEncoder, RlpList, RlpString} import play.api.libs.json.{JsObject, Json} +import units.BlockHash +import units.client.engine.model.EcBlock +import units.util.HexBytesConverter object EmptyL2Block { case class Params( diff --git a/src/main/scala/units/network/HistoryReplier.scala b/src/main/scala/units/network/HistoryReplier.scala index 8758df44..04db98ba 100644 --- a/src/main/scala/units/network/HistoryReplier.scala +++ b/src/main/scala/units/network/HistoryReplier.scala @@ -1,24 +1,20 @@ package units.network import cats.syntax.either.* -import units.client.engine.EngineApiClient -import units.client.http.EcApiClient -import units.util.BlockToPayloadMapper -import units.{BlockHash, ClientError, NetworkL2Block} import com.wavesplatform.network.id import com.wavesplatform.utils.ScorexLogging import io.netty.channel.ChannelHandler.Sharable import io.netty.channel.{ChannelHandlerContext, ChannelInboundHandlerAdapter} import monix.execution.Scheduler +import units.client.engine.EngineApiClient +import units.util.BlockToPayloadMapper +import units.{BlockHash, ClientError, NetworkL2Block} import scala.concurrent.Future import scala.util.{Failure, Success} @Sharable -class HistoryReplier(httpApiClient: EcApiClient, engineApiClient: EngineApiClient)(implicit sc: Scheduler) - extends ChannelInboundHandlerAdapter - with ScorexLogging { - +class HistoryReplier(engineApiClient: EngineApiClient)(implicit sc: Scheduler) extends ChannelInboundHandlerAdapter with ScorexLogging { private def respondWith(ctx: ChannelHandlerContext, value: Future[Message]): Unit = value.onComplete { case Failure(e) => log.debug(s"${id(ctx)} Error processing request", e) @@ -46,7 +42,7 @@ class HistoryReplier(httpApiClient: EcApiClient, engineApiClient: EngineApiClien private def loadBlockL2(hash: BlockHash): Future[Either[ClientError, NetworkL2Block]] = Future { for { - blockJsonOpt <- httpApiClient.getBlockByHashJson(hash) + blockJsonOpt <- engineApiClient.getBlockByHashJson(hash) blockJson <- Either.fromOption(blockJsonOpt, ClientError("block not found")) payloadBodyJsonOpt <- engineApiClient.getPayloadBodyByHash(hash) payloadBodyJson <- Either.fromOption(payloadBodyJsonOpt, ClientError("payload body not found")) diff --git a/src/test/scala/units/BaseIntegrationTestSuite.scala b/src/test/scala/units/BaseIntegrationTestSuite.scala index 1cc382c4..aff7d105 100644 --- a/src/test/scala/units/BaseIntegrationTestSuite.scala +++ b/src/test/scala/units/BaseIntegrationTestSuite.scala @@ -11,7 +11,7 @@ import com.wavesplatform.utils.ScorexLogging import org.scalatest.freespec.AnyFreeSpec import org.scalatest.{BeforeAndAfterAll, EitherValues, OptionValues} import units.Bridge.ElSentNativeEvent -import units.client.http.model.GetLogsResponseEntry +import units.client.engine.model.GetLogsResponseEntry import units.eth.{EthAddress, Gwei} import units.test.CustomMatchers import units.util.HexBytesConverter @@ -37,7 +37,7 @@ trait BaseIntegrationTestSuite val txs = List( d.chainContract.setScript(), - d.chainContract.setup(d.ecGenesisBlock, elMinerDefaultReward.amount.longValue(), elBridgeAddress) + d.chainContract.setup(d.ecGenesisBlock, elMinerDefaultReward.amount.longValue()) ) ++ settings.initialMiners .flatMap { x => @@ -69,6 +69,7 @@ trait BaseIntegrationTestSuite blockchainUpdater = bcu, rocksDBWriter = blockchain, settings = settings.wavesSettings, + elBridgeAddress = elBridgeAddress, elMinerDefaultReward = elMinerDefaultReward ) diff --git a/src/test/scala/units/BlockFullValidationTestSuite.scala b/src/test/scala/units/BlockFullValidationTestSuite.scala index 69b3c164..9aff63b0 100644 --- a/src/test/scala/units/BlockFullValidationTestSuite.scala +++ b/src/test/scala/units/BlockFullValidationTestSuite.scala @@ -4,7 +4,7 @@ import com.wavesplatform.common.utils.EitherExt2 import com.wavesplatform.transaction.TxHelpers import units.ELUpdater.State.ChainStatus.{FollowingChain, WaitForNewChain} import units.client.contract.HasConsensusLayerDappTxHelpers.EmptyE2CTransfersRootHashHex -import units.client.http.model.{EcBlock, GetLogsResponseEntry} +import units.client.engine.model.{EcBlock, GetLogsResponseEntry} import units.eth.EthAddress import units.util.HexBytesConverter diff --git a/src/test/scala/units/BlockIssuesForgingTestSuite.scala b/src/test/scala/units/BlockIssuesForgingTestSuite.scala index a1cec3b2..d17cfb10 100644 --- a/src/test/scala/units/BlockIssuesForgingTestSuite.scala +++ b/src/test/scala/units/BlockIssuesForgingTestSuite.scala @@ -6,7 +6,7 @@ import com.wavesplatform.wallet.Wallet import units.ELUpdater.State.ChainStatus.{FollowingChain, Mining, WaitForNewChain} import units.ELUpdater.WaitRequestedBlockTimeout import units.client.contract.HasConsensusLayerDappTxHelpers.defaultFees -import units.client.http.model.EcBlock +import units.client.engine.model.EcBlock import scala.concurrent.duration.DurationInt diff --git a/src/test/scala/units/ExtensionDomain.scala b/src/test/scala/units/ExtensionDomain.scala index 9c969969..5c264fb4 100644 --- a/src/test/scala/units/ExtensionDomain.scala +++ b/src/test/scala/units/ExtensionDomain.scala @@ -41,7 +41,7 @@ import units.ELUpdater.State.{ChainStatus, Working} import units.ExtensionDomain.* import units.client.contract.HasConsensusLayerDappTxHelpers import units.client.contract.HasConsensusLayerDappTxHelpers.EmptyE2CTransfersRootHashHex -import units.client.http.model.{EcBlock, TestEcBlocks} +import units.client.engine.model.{EcBlock, TestEcBlocks} import units.client.{L2BlockLike, TestEcClients} import units.eth.{EthAddress, EthereumConstants, Gwei} import units.network.TestBlocksObserver @@ -58,6 +58,7 @@ class ExtensionDomain( blockchainUpdater: BlockchainUpdaterImpl, rocksDBWriter: RocksDBWriter, settings: WavesSettings, + override val elBridgeAddress: EthAddress, elMinerDefaultReward: Gwei ) extends Domain(rdb, blockchainUpdater, rocksDBWriter, settings) with HasConsensusLayerDappTxHelpers @@ -122,7 +123,6 @@ class ExtensionDomain( l2Config, extensionContext, ecClients.engineApi, - ecClients.ecApi, blockObserver, allChannels, globalScheduler, @@ -346,7 +346,7 @@ class ExtensionDomain( createEcBlockBuilder(hashPath, miner.elRewardAddress, parent) def createEcBlockBuilder(hashPath: String, minerRewardL2Address: EthAddress, parent: EcBlock): TestEcBlockBuilder = - TestEcBlockBuilder(ecClients, elMinerDefaultReward, l2Config.blockDelay, parent = parent).updateBlock( + TestEcBlockBuilder(ecClients, elBridgeAddress, elMinerDefaultReward, l2Config.blockDelay, parent = parent).updateBlock( _.copy( hash = TestEcBlockBuilder.createBlockHash(hashPath), minerRewardL2Address = minerRewardL2Address diff --git a/src/test/scala/units/TestEcBlockBuilder.scala b/src/test/scala/units/TestEcBlockBuilder.scala index 817d6453..ca451a3d 100644 --- a/src/test/scala/units/TestEcBlockBuilder.scala +++ b/src/test/scala/units/TestEcBlockBuilder.scala @@ -2,8 +2,7 @@ package units import org.web3j.abi.datatypes.generated.Uint256 import units.client.TestEcClients -import units.client.engine.model.Withdrawal -import units.client.http.model.{EcBlock, GetLogsResponseEntry} +import units.client.engine.model.{EcBlock, GetLogsResponseEntry, Withdrawal} import units.eth.{EthAddress, EthereumConstants, Gwei} import java.nio.charset.StandardCharsets @@ -11,6 +10,7 @@ import scala.concurrent.duration.FiniteDuration class TestEcBlockBuilder private ( testEcClients: TestEcClients, + elBridgeAddress: EthAddress, elMinerDefaultReward: Gwei, private var block: EcBlock, parentBlock: EcBlock @@ -29,7 +29,7 @@ class TestEcBlockBuilder private ( def build(): EcBlock = block def buildAndSetLogs(logs: List[GetLogsResponseEntry] = Nil): EcBlock = { - testEcClients.setBlockLogs(block.hash, Bridge.ElSentNativeEventTopic, logs) + testEcClients.setBlockLogs(block.hash, elBridgeAddress, Bridge.ElSentNativeEventTopic, logs) block } } @@ -37,12 +37,14 @@ class TestEcBlockBuilder private ( object TestEcBlockBuilder { def apply( testEcClients: TestEcClients, + elBridgeAddress: EthAddress, elMinerDefaultReward: Gwei, blockDelay: FiniteDuration, parent: EcBlock ): TestEcBlockBuilder = new TestEcBlockBuilder( testEcClients, + elBridgeAddress, elMinerDefaultReward, EcBlock( hash = createBlockHash("???"), diff --git a/src/test/scala/units/client/TestEcClients.scala b/src/test/scala/units/client/TestEcClients.scala index 01004425..ed33382d 100644 --- a/src/test/scala/units/client/TestEcClients.scala +++ b/src/test/scala/units/client/TestEcClients.scala @@ -9,10 +9,8 @@ import play.api.libs.json.JsObject import units.ELUpdater.calculateRandao import units.client.TestEcClients.* import units.client.engine.EngineApiClient.PayloadId -import units.client.engine.model.Withdrawal +import units.client.engine.model.* import units.client.engine.{EngineApiClient, LoggedEngineApiClient} -import units.client.http.model.* -import units.client.http.{EcApiClient, LoggedEcApiClient} import units.collections.ListOps.* import units.eth.{EthAddress, EthereumConstants} import units.{BlockHash, Job, NetworkL2Block} @@ -64,8 +62,8 @@ class TestEcClients private ( forgingBlocks.transform(ForgingBlock(mkTestEcBlock(ecBlock, epochNumber)) :: _) private val logs = Atomic(Map.empty[GetLogsRequest, List[GetLogsResponseEntry]]) - def setBlockLogs(hash: BlockHash, topic: String, blockLogs: List[GetLogsResponseEntry]): Unit = { - val request = GetLogsRequest(hash, List(topic)) + def setBlockLogs(hash: BlockHash, address: EthAddress, topic: String, blockLogs: List[GetLogsResponseEntry]): Unit = { + val request = GetLogsRequest(hash, address, List(topic)) logs.transform(_.updated(request, blockLogs)) } @@ -75,7 +73,7 @@ class TestEcClients private ( */ def fullValidatedBlocks: Set[BlockHash] = getLogsCalls.get() - val engineApi = LoggedEngineApiClient { + val engineApi = new LoggedEngineApiClient( new EngineApiClient { override def forkChoiceUpdate(blockHash: BlockHash, finalizedBlockHash: BlockHash): Job[String] = { knownBlocks.get().get(blockHash) match { @@ -143,12 +141,8 @@ class TestEcClients private ( }.asRight override def getPayloadBodyByHash(hash: BlockHash): Job[Option[JsObject]] = - ecApi.getBlockByHashJson(hash) - } - } + getBlockByHashJson(hash) - val ecApi = LoggedEcApiClient { - new EcApiClient { override def getBlockByNumber(number: BlockNumber): Job[Option[EcBlock]] = number match { case BlockNumber.Latest => currChain.headOption.asRight @@ -163,20 +157,20 @@ class TestEcClients private ( } yield b.ecBlock }.asRight - override def getBlockByHashJson(hash: BlockHash, fullTxs: Boolean): Job[Option[JsObject]] = + override def getBlockByHashJson(hash: BlockHash): Job[Option[JsObject]] = notImplementedMethodJob("getBlockByHashJson") override def getLastExecutionBlock: Job[EcBlock] = currChain.head.asRight override def blockExists(hash: BlockHash): Job[Boolean] = notImplementedMethodJob("blockExists") - override def getLogs(hash: BlockHash, topic: String): Job[List[GetLogsResponseEntry]] = { - val request = GetLogsRequest(hash, List(topic)) + override def getLogs(hash: BlockHash, address: EthAddress, topic: String): Job[List[GetLogsResponseEntry]] = { + val request = GetLogsRequest(hash, address, List(topic)) getLogsCalls.transform(_ + hash) logs.get().getOrElse(request, throw notImplementedCase("call setBlockLogs")) }.asRight } - } + ) protected def notImplementedMethodJob[A](text: String): Job[A] = throw new NotImplementedMethod(text) protected def notImplementedCase(text: String): Throwable = new NotImplementedCase(text) diff --git a/src/test/scala/units/client/contract/HasConsensusLayerDappTxHelpers.scala b/src/test/scala/units/client/contract/HasConsensusLayerDappTxHelpers.scala index 3ee53431..8e7a8061 100644 --- a/src/test/scala/units/client/contract/HasConsensusLayerDappTxHelpers.scala +++ b/src/test/scala/units/client/contract/HasConsensusLayerDappTxHelpers.scala @@ -17,6 +17,8 @@ import units.eth.{EthAddress, EthereumConstants} import units.util.HexBytesConverter trait HasConsensusLayerDappTxHelpers { + def elBridgeAddress: EthAddress + def currentHitSource: ByteStr def stakingContractAccount: KeyPair @@ -44,7 +46,7 @@ trait HasConsensusLayerDappTxHelpers { object chainContract { def setScript(): SetScriptTransaction = TxHelpers.setScript(chainContractAccount, CompiledChainContract.script, fee = setScriptFee) - def setup(genesisBlock: L2BlockLike, elMinerReward: Long, elBridgeAddress: EthAddress): InvokeScriptTransaction = TxHelpers.invoke( + def setup(genesisBlock: L2BlockLike, elMinerReward: Long): InvokeScriptTransaction = TxHelpers.invoke( dApp = chainContractAddress, func = "setup".some, args = List( diff --git a/src/test/scala/units/client/engine/LoggedEngineApiClient.scala b/src/test/scala/units/client/engine/LoggedEngineApiClient.scala deleted file mode 100644 index 21100cf9..00000000 --- a/src/test/scala/units/client/engine/LoggedEngineApiClient.scala +++ /dev/null @@ -1,36 +0,0 @@ -package units.client.engine - -import play.api.libs.json.JsObject -import units.client.engine.EngineApiClient.PayloadId -import units.client.engine.model.Withdrawal -import units.eth.EthAddress -import units.{BlockHash, HasJobLogging, Job} - -class LoggedEngineApiClient(underlying: EngineApiClient) extends EngineApiClient with HasJobLogging { - override def forkChoiceUpdate(blockHash: BlockHash, finalizedBlockHash: BlockHash): Job[String] = - wrap(s"forkChoiceUpdate($blockHash, f=$finalizedBlockHash)", underlying.forkChoiceUpdate(blockHash, finalizedBlockHash)) - - override def forkChoiceUpdateWithPayloadId( - lastBlockHash: BlockHash, - finalizedBlockHash: BlockHash, - unixEpochSeconds: Long, - suggestedFeeRecipient: EthAddress, - prevRandao: String, - withdrawals: Vector[Withdrawal] - ): Job[PayloadId] = wrap( - s"forkChoiceUpdateWithPayloadId(lastBlockHash=$lastBlockHash, f=$finalizedBlockHash, ts=$unixEpochSeconds, feeRecipient=$suggestedFeeRecipient, " + - s"prd=$prevRandao, w={${withdrawals.mkString(", ")}}", - underlying.forkChoiceUpdateWithPayloadId(lastBlockHash, finalizedBlockHash, unixEpochSeconds, suggestedFeeRecipient, prevRandao, withdrawals) - ) - - override def getPayload(payloadId: PayloadId): Job[JsObject] = wrap(s"getPayload($payloadId)", underlying.getPayload(payloadId)) - - override def applyNewPayload(payload: JsObject): Job[Option[BlockHash]] = wrap(s"applyNewPayload($payload)", underlying.applyNewPayload(payload)) - - override def getPayloadBodyByHash(hash: BlockHash): Job[Option[JsObject]] = - wrap(s"getPayloadBodyByHash($hash)", underlying.getPayloadBodyByHash(hash)) -} - -object LoggedEngineApiClient { - def apply(underlying: EngineApiClient): EngineApiClient = new LoggedEngineApiClient(underlying) -} diff --git a/src/test/scala/units/client/http/model/TestEcBlocks.scala b/src/test/scala/units/client/engine/model/TestEcBlocks.scala similarity index 96% rename from src/test/scala/units/client/http/model/TestEcBlocks.scala rename to src/test/scala/units/client/engine/model/TestEcBlocks.scala index d0fe70aa..389f9d91 100644 --- a/src/test/scala/units/client/http/model/TestEcBlocks.scala +++ b/src/test/scala/units/client/engine/model/TestEcBlocks.scala @@ -1,4 +1,4 @@ -package units.client.http.model +package units.client.engine.model import com.wavesplatform.account.SeedKeyPair import com.wavesplatform.common.utils.EitherExt2 diff --git a/src/test/scala/units/client/http/LoggedEcApiClient.scala b/src/test/scala/units/client/http/LoggedEcApiClient.scala deleted file mode 100644 index e1b340c1..00000000 --- a/src/test/scala/units/client/http/LoggedEcApiClient.scala +++ /dev/null @@ -1,25 +0,0 @@ -package units.client.http - -import play.api.libs.json.JsObject -import units.client.http.model.{BlockNumber, EcBlock, GetLogsResponseEntry} -import units.{BlockHash, HasJobLogging, Job} - -class LoggedEcApiClient(underlying: EcApiClient) extends EcApiClient with HasJobLogging { - override def getBlockByNumber(number: BlockNumber): Job[Option[EcBlock]] = wrap(s"getBlockByNumber($number)", underlying.getBlockByNumber(number)) - - override def getBlockByHash(hash: BlockHash): Job[Option[EcBlock]] = wrap(s"getBlockByHash($hash)", underlying.getBlockByHash(hash)) - - override def getBlockByHashJson(hash: BlockHash, fullTxs: Boolean): Job[Option[JsObject]] = - wrap(s"getBlockByHashJson($hash, fullTxs=$fullTxs)", underlying.getBlockByHashJson(hash, fullTxs)) - - override def getLastExecutionBlock: Job[EcBlock] = wrap("getLastExecutionBlock", underlying.getLastExecutionBlock) - - override def blockExists(hash: BlockHash): Job[Boolean] = wrap(s"blockExists($hash)", underlying.blockExists(hash)) - - override def getLogs(hash: BlockHash, topic: String): Job[List[GetLogsResponseEntry]] = - wrap(s"getLogs($hash, $topic)", underlying.getLogs(hash, topic)) -} - -object LoggedEcApiClient { - def apply(underlying: EcApiClient): EcApiClient = new LoggedEcApiClient(underlying) -} diff --git a/src/test/scala/units/eth/EmptyL2BlockTestSuite.scala b/src/test/scala/units/eth/EmptyL2BlockTestSuite.scala index ae3de91c..c965af99 100644 --- a/src/test/scala/units/eth/EmptyL2BlockTestSuite.scala +++ b/src/test/scala/units/eth/EmptyL2BlockTestSuite.scala @@ -5,7 +5,7 @@ import org.scalatest.freespec.AnyFreeSpec import org.web3j.abi.datatypes.generated.Uint256 import play.api.libs.json.Json import units.BlockHash -import units.client.http.model.EcBlock +import units.client.engine.model.EcBlock import units.eth.EmptyL2Block.Params class EmptyL2BlockTestSuite extends AnyFreeSpec with BaseSuite {