From 237ad2cb2ea42803837a5d2fea23fbba8d436387 Mon Sep 17 00:00:00 2001 From: Yashk767 <76935991+Yashk767@users.noreply.github.com> Date: Wed, 14 Dec 2022 12:46:01 +0530 Subject: [PATCH] Merge v1.0.5 to main (#1038) * v1.2.0 (#965) * Hotfix-logImprovements (#952) * Set up blocknumber and epoch in logs * updated blocknumber and epoch logger info in every command * Hotfix-getDataFromAPI (#951) * Changed numm of retry attempts * removed redundant retry attempts * corrected tests * changed http timeout and logged time elapsed to fetch data (#954) * Updated version (#960) * Updated version * updated version to v1.2.0 * version update (#972) * Merged `v1.3.0-alpha` into `v1.0.5` (#973) * Merged `v1` into `v1.3.0-aplha` with hotfixes (#966) * Hotfix-proposed data (#913) * Updated propose data global variables correctly * Fixed tests * Returned correct waitForBlockCompletion error * coverage increase * GetLocalData returns type types.ProposeFileData * fixed benchmark * Fetched Last proposed from contracts (#917) * fetched getLastProposedEpoch from contracts and tests for it * typo fix * V1 propose hotfix (#918) * Change propose.go to get sorted proposed block ids. * Fix sorted proposed block issue. Signed-off-by: Ashish Kumar Mishra * allow stakers to addStake < minSafeRazor (#928) * Call claimStakerReward only if there reward to claim (#926) * Make contract call only if there is commission to claim * Add tests for claimCommission file * update check * Hotfix-giveSorted (#921) * ResetDispute only done after FinalizeDispute * Fixed tests * Update README (#931) * Update README * Update logs path * Fix home dir path * Add logs to vote.go and commit.go Signed-off-by: Ashish Kumar Mishra * Add logs for dispute and propose. Signed-off-by: Ashish Kumar Mishra * Fix tests. Signed-off-by: Ashish Kumar Mishra * Suppress unneccessary error logs. (#935) Signed-off-by: Ashish Kumar Mishra * changed http timeout to 30 sec (#943) * saving commit data only after successfull commit (#947) * Added password flag (#946) * added password flag * README updated * Hotfix-giveSorted (new implementation) (#953) * GiveSorted linear recursion * Added backupNode flag * Compilation success for tests * Fixed tests * removed recusrsion, called giveSorted linearly * fixed tests * Added leafId to giveSortedLeafIds[] on successful giveSorted * Hotfix-sortedProposedBlocks (#957) * Shuffled copied slice instead of original slice * returned error from giveSorted when len(sortedValues)=0 * Fixed dispute tests * Changed pending nonce at to nonce at. (#948) * Changed pending nonce at to nonce at. * Update mockery Signed-off-by: Ashish Kumar Mishra * Hotfix -RPCTimeout (#955) * Added a generic function with timeout for contract calls * Moved generic function to utils and implemented to all contract getter calls * Implemented timeout for contract setter functions * rpc timeout custom error * type asserting structs from contract mappings * Shifted timeout to constants * passed timeout in int in constants.go * Added rpcTimeout as config * Removed errorIndex paramter from CheckIfAnyError() * Function renamed * Fixed tests * Unrequired change * Added backup node info in readme (#963) * Passed a initialized varible instead of nil value as a parameter Signed-off-by: Ashish Kumar Mishra Co-authored-by: Shekhar Gaur <65169767+shekhar2807@users.noreply.github.com> Co-authored-by: Ashish Kumar Mishra Co-authored-by: Shyam Patel Co-authored-by: Raj Kharvar Co-authored-by: Skanda Bhat * Updated `v1.3.0` branch to staging parameters for v1.3.0-alpha version (#967) * Updated contract addresses and chainId to staging * Updated razor-go version to v1.3.0-alpha * Fixed `CheckIfAnyError()` on RPCTimeout. (#974) * Added errorIndexInReturnedValues as a parameter in function * Fixed comparios of error data type from returned values * Added a check if config key is present in yaml file before fetching value (#975) * Added default values for config parameters * Checked if config key is present in yaml file before fetching * Fixed tests * returned default values uniformly Signed-off-by: Ashish Kumar Mishra Co-authored-by: Shekhar Gaur <65169767+shekhar2807@users.noreply.github.com> Co-authored-by: Ashish Kumar Mishra Co-authored-by: Shyam Patel Co-authored-by: Raj Kharvar Co-authored-by: Skanda Bhat * updated version to v1.0.5-alpha (#978) * Changes Requested in v1.0.5 Review (#1006) * updated logs and readMe for v1.0.5 * Canges string formater for errors to %v * Inserted Logs in the entire codebase (#1018) * Inserted Logs * Corrected logs * Modified lumberJack constants * V1.0.5-alpha-patch1 Ready (#1022) * Merge `v1.0.4` release to main branch (#977) * v1.2.0 (#965) * Hotfix-logImprovements (#952) * Set up blocknumber and epoch in logs * updated blocknumber and epoch logger info in every command * Hotfix-getDataFromAPI (#951) * Changed numm of retry attempts * removed redundant retry attempts * corrected tests * changed http timeout and logged time elapsed to fetch data (#954) * Updated version (#960) * Updated version * updated version to v1.2.0 * version update (#972) * Updated user in dockerfile (#1012) * updating user in dockerfile * updating readme for non-root user * Log corrections * updated release * Revert "Updated user in dockerfile (#1012)" (#1021) This reverts commit 7f95edbdc1c2963077805a9da6b0b5aa7e4c0f22. Co-authored-by: Shrikant upadhyay * Calculated blockNumber in a separate go-routine for logging (#1025) * Cached block number in logger * Revert "Cached block number in logger" This reverts commit 760e3adf38f106bd444ef2d64494565d9bd6dae1. * Added block/block.go for calculating latestBlock in a seperate goroutine * Fetched block number from block package * log corrections * Increased max size of file to 182MB (#1027) * V1.0.5 beta ready (#1032) * Production support * Updated release version * Updated maxSize of log file to 200MB * Added mutex lock in blockNumber calculation (#1035) * Merge `v1.0.4` release to main branch (#977) * v1.2.0 (#965) * Hotfix-logImprovements (#952) * Set up blocknumber and epoch in logs * updated blocknumber and epoch logger info in every command * Hotfix-getDataFromAPI (#951) * Changed numm of retry attempts * removed redundant retry attempts * corrected tests * changed http timeout and logged time elapsed to fetch data (#954) * Updated version (#960) * Updated version * updated version to v1.2.0 * version update (#972) * Updated user in dockerfile (#1012) * updating user in dockerfile * updating readme for non-root user * Revert "Updated user in dockerfile (#1012)" (#1021) This reverts commit 7f95edbdc1c2963077805a9da6b0b5aa7e4c0f22. * Added mutex lock in blockNumber calculation * Added new staging addresses and chainId * updated version Co-authored-by: Shrikant upadhyay * v1.0.5-beta-patch1 (#1037) * Updated depolyment paramters to prod * updated version to v1.0.5-beta-patch1 * Updated version to v1.0.5 (#1033) * Made v1.0.5 branch in sync with main branch (#1039) * Merge `v1.0.4` release to main branch (#977) * v1.2.0 (#965) * Hotfix-logImprovements (#952) * Set up blocknumber and epoch in logs * updated blocknumber and epoch logger info in every command * Hotfix-getDataFromAPI (#951) * Changed numm of retry attempts * removed redundant retry attempts * corrected tests * changed http timeout and logged time elapsed to fetch data (#954) * Updated version (#960) * Updated version * updated version to v1.2.0 * version update (#972) * Updated user in dockerfile (#1012) * updating user in dockerfile * updating readme for non-root user * Revert "Updated user in dockerfile (#1012)" (#1021) This reverts commit 7f95edbdc1c2963077805a9da6b0b5aa7e4c0f22. Co-authored-by: Shrikant upadhyay * Deleted password file (#1040) Signed-off-by: Ashish Kumar Mishra Co-authored-by: Shekhar Gaur <65169767+shekhar2807@users.noreply.github.com> Co-authored-by: Ashish Kumar Mishra Co-authored-by: Shyam Patel Co-authored-by: Raj Kharvar Co-authored-by: Skanda Bhat Co-authored-by: Shrikant upadhyay --- README.md | 181 +++++++++--- block/block.go | 40 +++ cmd/addStake.go | 24 +- cmd/addStake_test.go | 29 +- cmd/approve.go | 2 + cmd/claimBounty.go | 34 ++- cmd/claimBounty_test.go | 2 +- cmd/claimCommission.go | 68 +++-- cmd/claimCommission_test.go | 168 ++++++++++-- cmd/cmd-utils.go | 2 + cmd/collectionList.go | 3 + cmd/commit.go | 23 +- cmd/config-utils.go | 90 +++++- cmd/config-utils_test.go | 98 ++++++- cmd/confirm.go | 5 + cmd/contractAddresses.go | 1 + cmd/create.go | 15 +- cmd/createCollection.go | 19 +- cmd/createCollection_test.go | 2 +- cmd/createJob.go | 17 +- cmd/createJob_test.go | 2 +- cmd/create_test.go | 2 +- cmd/delegate.go | 17 +- cmd/delegate_test.go | 2 +- cmd/dispute.go | 304 ++++++++++++++------ cmd/dispute_test.go | 350 ++++++++++++----------- cmd/import.go | 10 +- cmd/initiateWithdraw.go | 29 +- cmd/initiateWithdraw_test.go | 2 +- cmd/interface.go | 24 +- cmd/jobList.go | 4 +- cmd/listAccounts.go | 6 +- cmd/mocks/block_manager_interface.go | 25 ++ cmd/mocks/flag_set_interface.go | 65 +++++ cmd/mocks/utils_cmd_interface.go | 143 +++++----- cmd/mocks/utils_interface.go | 41 ++- cmd/modifyCollectionStatus.go | 11 +- cmd/modifyCollectionStatus_test.go | 2 +- cmd/propose.go | 170 ++++++++---- cmd/propose_test.go | 149 ++++++---- cmd/resetUnstakeLock.go | 9 +- cmd/resetUnstakeLock_test.go | 2 +- cmd/reveal.go | 16 +- cmd/root.go | 3 + cmd/setConfig.go | 31 ++- cmd/setConfig_test.go | 21 ++ cmd/setDelegation.go | 16 +- cmd/setDelegation_test.go | 2 +- cmd/stakerInfo.go | 3 + cmd/struct-utils.go | 177 +++++++++--- cmd/transfer.go | 15 +- cmd/transfer_test.go | 2 +- cmd/unlockWithdraw.go | 25 +- cmd/unlockWithdraw_test.go | 2 +- cmd/unstake.go | 16 +- cmd/unstake_test.go | 2 +- cmd/updateCollection.go | 19 +- cmd/updateCollection_test.go | 2 +- cmd/updateCommission.go | 24 +- cmd/updateCommission_test.go | 2 +- cmd/updateJob.go | 19 +- cmd/updateJob_test.go | 2 +- cmd/vote.go | 266 ++++++++++-------- cmd/vote_test.go | 193 +------------ config.sh | 2 +- core/constants.go | 17 +- core/types/block.go | 7 + core/types/configurations.go | 1 + core/version.go | 2 +- logger/logger.go | 32 +-- utils/asset.go | 6 +- utils/block.go | 20 ++ utils/block_test.go | 61 ++++ utils/client_methods.go | 4 +- utils/client_methods_test.go | 10 +- utils/common.go | 13 +- utils/common_test.go | 5 +- utils/interface.go | 9 +- utils/math.go | 10 +- utils/math_test.go | 15 +- utils/mocks/block_manager_utils.go | 21 ++ utils/mocks/client_utils.go | 4 +- utils/mocks/utils.go | 73 +++-- utils/options.go | 5 +- utils/options_test.go | 2 +- utils/password.go | 29 +- utils/struct-utils.go | 397 ++++++++++++++++++++++++--- 87 files changed, 2668 insertions(+), 1127 deletions(-) create mode 100644 block/block.go diff --git a/README.md b/README.md index e852bca0..31f1e36a 100644 --- a/README.md +++ b/README.md @@ -10,32 +10,45 @@ Official node for running stakers in Golang. Install `razor-go` pre build binary directly from github and configure into host. - For linux-amd64 - ``` - curl -sSL https://raw.githubusercontent.com/razor-network/razor-go/main/install.sh | bash - ``` +For linux-amd64 - For linux-arm64 - ``` - export PLATFORM=arm64 +``` +curl -sSL https://raw.githubusercontent.com/razor-network/razor-go/main/install.sh | bash +``` - curl -sSL https://raw.githubusercontent.com/razor-network/razor-go/main/install.sh | bash - ``` +For linux-arm64 + +``` +export PLATFORM=arm64 + +curl -sSL https://raw.githubusercontent.com/razor-network/razor-go/main/install.sh | bash +``` Check installation ``` razor -v ``` ->**_NOTE:_** To install the version you want, you can set VERSION: environment variable before running above command. + +> **_NOTE:_** To install the version you want, you can set VERSION: environment variable before running above command. + ## Docker quick start One of the quickest ways to get `razor-go` up and running on your machine is by using Docker: + +1. Create docker network + +``` +docker network create razor_network +``` + +2. Start razor-go container + ``` -docker run -d -it--entrypoint /bin/sh --name razor-go -v "$(echo $HOME)"/.razor:/root/.razor razornetwork/razor-go:v1.0.1-incentivised-testnet-phase2 +docker run -d -it --entrypoint /bin/sh --network=razor_network --name razor-go -v "$(echo $HOME)"/.razor:/root/.razor razornetwork/razor-go:v1.0.0-mainnet ``` ->**_NOTE:_** that we are leveraging docker bind-mounts to mount `.razor` directory so that we have a shared mount of `.razor` directory between the host and the container. The `.razor` directory holds keys to the addresses that we use in `razor-go`, along with logs and config. We do this to persist data in the host machine, otherwise you would lose your keys once you delete the container. +> **_NOTE:_** we are leveraging docker bind-mounts to mount `.razor` directory so that we have a shared mount of `.razor` directory between the host and the container. The `.razor` directory holds keys to the addresses that we use in `razor-go`, along with logs and config. We do this to persist data in the host machine, otherwise you would lose your keys once you delete the container. You need to set a provider before you can operate razor-go cli on docker: @@ -56,6 +69,7 @@ docker exec -it razor-go razor - Silicon chip based Mac users must go for node 15.3.0+ - `geth` and `abigen` should be installed. (Skip this step if you don't want to fetch the bindings and build from scratch) - `solc` and `jq` must be installed. + ### Building the source 1. Run `npm install` to install the node dependencies. @@ -74,7 +88,6 @@ Go to the `build/bin` directory where the razor binary is generated. `cd build/bin` - ### Set Config There are a set of parameters that are configurable. These include: @@ -82,29 +95,30 @@ There are a set of parameters that are configurable. These include: - Provider: The RPC URL of the provider you are using to connect to the blockchain. - Gas Multiplier: The value with which the gas price will be multiplied while sending every transaction. - Buffer Size: Buffer size determines, out of all blocks in a state, in how many blocks the voting or any other operation can be performed. -- Wait Time: This is the number of blocks the system will wait while voting. +- Wait Time: This is the number of seconds the system will wait while voting. - Gas Price: The value of gas price if you want to set manually. If you don't provide any value or simply keep it to 1, the razor client will automatically calculate the optimum gas price and send it. - Log Level: Normally debug logs are not logged into the log file. But if you want you can set `logLevel` to `debug` and fetch the debug logs. - Gas Limit: The value with which the gas limit will be multiplied while sending every transaction. +- RPC Timeout: This is the threshold number of seconds after which any contract and client calls will time out. The config is set while the build is generated, but if you need to change any of the above parameter, you can use the `setConfig` command. razor cli ``` -$ ./razor setConfig --provider --gasmultiplier --buffer --wait --gasprice --logLevel --gasLimit +$ ./razor setConfig --provider --gasmultiplier --buffer --wait --gasprice --logLevel --gasLimit --rpcTimeout ``` docker ``` -docker exec -it razor-go razor setConfig --provider --gasmultiplier --buffer --wait --gasprice --logLevel --gasLimit +docker exec -it razor-go razor setConfig --provider --gasmultiplier --buffer --wait --gasprice --logLevel --gasLimit --rpcTimeout ``` Example: ``` -$ ./razor setConfig --provider https://infura/v3/matic --gasmultiplier 1.5 --buffer 20 --wait 70 --gasprice 1 --logLevel debug --gasLimit 0.8 +$ ./razor setConfig --provider https://mainnet.skalenodes.com/v1/turbulent-unique-scheat --gasmultiplier 1 --buffer 20 --wait 30 --gasprice 0 --logLevel debug --gasLimit 2 --rpcTimeout 10 ``` Other than setting these parameters in the config, you can use different values of these parameters in different command. Just add the same flag to any command you want to use and the new config changes will appear for that command. @@ -117,8 +131,6 @@ $ ./razor vote --address 0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c --gasprice 1 This will cause this particular vote command to run with a gas price of 10. - - ## Razor commands ### Create Account @@ -137,6 +149,7 @@ Docker ``` docker exec -it razor-go razor create ``` + Example: ``` @@ -300,26 +313,26 @@ Example: $ ./razor delegate --address 0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c --value 1000 --weiRazor false --stakerId 1 ``` -### Claim Commission +### Claim Commission Staker can claim the rewards earned from delegator's pool share as commission using `claimCommission` razor cli ``` -$ ./razor claimCommission --address
+$ ./razor claimCommission --address
``` docker ``` -docker exec -it razor-go razor claimCommission --address
+docker exec -it razor-go razor claimCommission --address
``` Example: ``` -$ ./razor claimCommission --address 0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c +$ ./razor claimCommission --address 0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c ``` ### Vote @@ -339,18 +352,26 @@ docker exec -it razor-go razor vote --address
``` run vote command in background + ``` -docker exec -it -d razor-go razor vote --address
+docker exec -it -d razor-go razor vote --address
--password /root/.razor/ ``` - +>**_NOTE:_** To run command with password flag with the help of docker, password file should present in $HOME/.razor/ directory Example: ``` $ ./razor vote --address 0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c ``` + If you want to claim your bounty automatically after disputing staker, you can just pass `--autoClaimBounty` flag in your vote command. +If you are running an extra backup node, it is suggested to avoid performing few actions. So to do that you need to pass actions that need to be ignored as a value to flag `--backupNode `. +For now, we only support `disputeMedians` as actions to be ignored as a value for backup node. +``` +$ ./razor vote --address 0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c --backupNode disputeMedians +``` + If you want to report incorrect values, there is a `rogue` mode available. Just pass an extra flag `--rogue` to start voting in rogue mode and the client will report wrong medians. The rogueMode key can be used to specify in which particular voting state (commit, reveal) or for which values i.e. medians/revealedIds (medians, missingIds, extraIds, unsortedIds)you want to report incorrect values. @@ -397,6 +418,7 @@ $ ./razor initiateWithdraw --address
--stakerId ``` $ ./razor unlockWithdraw --address
--stakerId ``` + docker ``` @@ -412,6 +434,7 @@ Example: ``` $ ./razor initiateWithdraw --address 0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c --stakerId 1 ``` + ``` $ ./razor unlockWithdraw --address 0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c --stakerId 1 ``` @@ -442,10 +465,10 @@ $ ./razor extendLock --address 0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c --stak If you want to claim your bounty after disputing a rogue staker, you can run `claimBounty` command ->**_NOTE:_** bountyIds are stored in .razor directory with file name in format `YOUR_ADDRESS_disputeData.json file.` +> **_NOTE:_** bountyIds are stored in .razor directory with file name in format `YOUR_ADDRESS_disputeData.json file.` > > e.g: `0x2EDc3c6F93e4e20590F480272AB490D2620557xY_disputeData.json` -If you know the bountyId, you can pass the value to `bountyId` flag. +> If you know the bountyId, you can pass the value to `bountyId` flag. razor cli @@ -470,13 +493,13 @@ You can also run claimBounty command without passing `bountyId` flag as it will razor cli ``` -$ ./razor claimBounty --address
+$ ./razor claimBounty --address
``` docker ``` -docker exec -it razor-go razor claimBounty --address
+docker exec -it razor-go razor claimBounty --address
``` ### Transfer @@ -660,10 +683,13 @@ $ ./razor collectionList docker ``` -docker exec -it razor-go razorcollectionList +docker exec -it razor-go razor collectionList ``` +Note : _All the commands have an additional --password flag that you can provide with the file path from which password must be picked._ + ### Expose Metrics + Expose Prometheus-based metrics for monitoring Example: @@ -671,10 +697,13 @@ Example: razor cli Without TLS + ``` $ ./razor setConfig --exposeMetrics 2112 ``` + With TLS + ``` $ ./razor setConfig --exposeMetrics 2112 --certFile /cert/file/path/certfile.crt --certKey key/file/path/keyfile.key ``` @@ -693,12 +722,68 @@ docker exec -it razor-go razor setConfig --exposeMetrics 2112 docker exec -it razor-go razor setConfig --exposeMetrics 2112 --certFile /cert/file/path/certfile.crt --certKey key/file/path/keyfile.key ``` +#### Configuration + +Clone repo and setup monitoring and alerting using Prometheus/Grafana + +``` +git clone https://github.com/razor-network/monitoring.git +cd monitoring +``` + +- If your staker is running via binary, then + + 1. In `./configs/prometheus.yml`, replace `"razor-go:2112"` with `":2112"` + +- For alerting you can add webhook in `./configs/alertmanager.yml`, replace `http://127.0.0.1:5001/` with your webhook URL. This will send you an alert in every 5min if metrics stops. + +- If you are running multiple stakers and want to monitor via single grafana dashboard + 1. You need to update `./config/prometheus.yml`, add new target block where `job_name: "razor-go"` + ``` + - targets: [":2112"] + labels: + staker: "" + ``` + 2. Restart vmagent service `docker-compose restart vmagent` + +#### Start monitoring stack + +- You can spin all agents at once via + + ``` + docker-compose up -d + ``` + + Can check the status of each service via + + ``` + docker-compose ps + ``` + +- You can open grafana at `:3000`, and get + 1. Can checkout `Razor` dashboard to monitor your staker. + 2. Insight of host metrics at `Node Exporter Full` dashboard. + 3. Containers Insight at `Docker and OS metrics ( cadvisor, node_exporter )` dashboard. + 4. Can monitor alerts at `Alertmanager` dashboard. + +> **_NOTE:_** Configure firewall for port `3000` on your host to access grafana. + +#### Troubleshoot Alerting + +1. In `docker-compose.yml` uncomment ports for `alertmanager` and `vmalert`. +2. Configure firewall to allow access to ports `8880` and `9093`. + +3. Check you get alerts on vmalert via `http://:8880/vmalert/alerts`. vmalert is configured to scrap in every 2min. + +4. If you see alert in vmalert then look into alertmanager `http://:9093/#/alerts?`, if you see alerts in there but you didn't get one then probably you need to check your weebhook. + ### Override Job and Adding Your Custom Jobs Jobs URLs are a placeholder from where to fetch values from. There is a chance that these URLs might either fail, or get razor nodes blacklisted, etc. You can override the existing job and also add your custom jobs by adding `assets.json` file in `.razor` directory so that razor-nodes can fetch data directly from the provided jobs. Shown below is an example of how your `assets.json` file should be - + ``` { "assets": { @@ -728,9 +813,11 @@ Shown below is an example of how your `assets.json` file should be - ``` Breaking down into components + - The existing jobs that you want to override should be included in `official jobs` and fields like URL, selector should be replaced with your provided inputs respectively. In the above example for the collection `ethCollectionMean`, job having `jobId:1` is override by provided URL, selector, power and weight. + ``` "official jobs": { "1": { @@ -744,6 +831,7 @@ In the above example for the collection `ethCollectionMean`, job having `jobId:1 - Additional jobs that you want to add to a collection should be added in `custom jobs` field with their respective URLs and selectors. In the above example for the collection `ethCollectionMean`, new custom job having URL `https://api.lunarcrush.com/v2?data=assets&symbol=ETH` is added. + ``` "custom jobs": [ { @@ -757,30 +845,37 @@ In the above example for the collection `ethCollectionMean`, new custom job havi ### Logs -User can pass a separate flag --logFile followed with any name for log file along with command. The logs will be stored in ```.razor/logs``` directory. +User can pass a separate flag --logFile followed with any name for log file along with command. The logs will be stored in `.razor/logs` directory. razor cli + ``` $ ./razor addStake --address
--value --logFile stakingLogs ``` + docker + ``` docker exec -it razor-go razo addStake --address
--value --logFile stakingLogs ``` -_The logs for above command will be stored at "home/.razor/stakingLogs.log" path_ + +_The logs for above command will be stored at "$HOME/.razor/logs/stakingLogs.log" path_ razor cli + ``` $ ./razor delegate --address
--value --weiRazor --stakerId --logFile delegationLogs ``` + docker + ``` docker exec -it razor-go razo delegate --address
--value --weiRazor --stakerId --logFile delegationLogs ``` -_The logs for above command will be stored at "home/.razor/delegationLogs.log" path_ -_Note: If the user runs multiple commands with the same log file name all the logs will be appended in the same log file._ +_The logs for above command will be stored at "$HOME/.razor/logs/delegationLogs.log" path_ +_Note: If the user runs multiple commands with the same log file name all the logs will be appended in the same log file._ ### Contract Addresses @@ -804,7 +899,6 @@ Example: $ ./razor contractAddresses ``` - ### Setting up razor-go and commands using docker-compose 1. Must have `docker` and `docker-compose` installed @@ -839,12 +933,19 @@ $ ./razor contractAddresses docker-compose run razor-go /usr/local/bin/razor import ``` -7. Get some **RAZOR** and **MATIC** token (or Token of respective RPC) to this address +7. Get some **RAZOR** and **sFUEL** token (or Token of respective RPC) to this address 8. Start **Staking** ```bash #Provide password through CLI docker-compose run razor-go /usr/local/bin/razor addStake --address
--value 50000 + + #Provide password through File + + #Create file and put password string + vi ~/.razor/pass + #Start Staking + docker-compose run razor-go /usr/local/bin/razor addStake --address
--value 50000 --password /root/.razor/pass ``` 9. To Start **Voting**, @@ -854,6 +955,9 @@ $ ./razor contractAddresses ```bash # Run process in foreground and provide password through cli docker-compose run razor-go /usr/local/bin/razor vote --address
+ + # Run process in background and provide password through file + docker-compose run -d razor-go /usr/local/bin/razor vote --address
--password /root/.razor/pass ``` ```bash @@ -865,8 +969,11 @@ $ ./razor contractAddresses ```bash #Provide password with cli docker-compose run razor-go /usr/local/bin/razor setDelegation --address
--status true --commission 10 + + #provide password through file + docker-compose run razor-go /usr/local/bin/razor setDelegation --address
--status true --commission 10 --password /root/.razor/pass ``` ### Contribute to razor-go -We would really appreciate your contribution. To see our [contribution guideline](https://github.com/razor-network/razor-go/blob/main/.github/CONTRIBUTING.md) \ No newline at end of file +We would really appreciate your contribution. To see our [contribution guideline](https://github.com/razor-network/razor-go/blob/main/.github/CONTRIBUTING.md) diff --git a/block/block.go b/block/block.go new file mode 100644 index 00000000..35598d22 --- /dev/null +++ b/block/block.go @@ -0,0 +1,40 @@ +package block + +import ( + "context" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/sirupsen/logrus" + "razor/core" + "sync" + "time" +) + +var latestBlock *types.Header +var mu = sync.Mutex{} + +func GetLatestBlock() *types.Header { + mu.Lock() + defer mu.Unlock() + return latestBlock +} + +func SetLatestBlock(block *types.Header) { + mu.Lock() + latestBlock = block + mu.Unlock() +} + +func CalculateLatestBlock(client *ethclient.Client) { + for { + if client != nil { + latestHeader, err := client.HeaderByNumber(context.Background(), nil) + if err != nil { + logrus.Error("CalculateBlockNumber: Error in fetching block: ", err) + continue + } + SetLatestBlock(latestHeader) + } + time.Sleep(time.Second * time.Duration(core.BlockNumberInterval)) + } +} diff --git a/cmd/addStake.go b/cmd/addStake.go index 16de5140..4b02e5d3 100644 --- a/cmd/addStake.go +++ b/cmd/addStake.go @@ -34,30 +34,43 @@ func initialiseStake(cmd *cobra.Command, args []string) { func (*UtilsStruct) ExecuteStake(flagSet *pflag.FlagSet) { config, err := cmdUtils.GetConfigData() utils.CheckError("Error in getting config: ", err) + log.Debugf("ExecuteStake: config: %+v", config) client := razorUtils.ConnectToClient(config.Provider) address, err := flagSetUtils.GetStringAddress(flagSet) utils.CheckError("Error in getting address: ", err) + log.Debug("ExecuteStake: Address: ", address) logger.SetLoggerParameters(client, address) + log.Debug("Checking to assign log file...") razorUtils.AssignLogFile(flagSet) - password := razorUtils.AssignPassword() + log.Debug("Getting password...") + password := razorUtils.AssignPassword(flagSet) balance, err := razorUtils.FetchBalance(client, address) utils.CheckError("Error in fetching razor balance for account: "+address, err) + log.Debug("Getting amount in wei...") valueInWei, err := cmdUtils.AssignAmountInWei(flagSet) utils.CheckError("Error in getting amount: ", err) + log.Debug("ExecuteStake: Amount in wei: ", valueInWei) + log.Debug("Checking for sufficient balance...") razorUtils.CheckAmountAndBalance(valueInWei, balance) + log.Debug("Checking whether sFuel balance is not 0...") razorUtils.CheckEthBalanceIsZero(client, address) minSafeRazor, err := utils.UtilsInterface.GetMinSafeRazor(client) utils.CheckError("Error in getting minimum safe razor amount: ", err) + log.Debug("ExecuteStake: Minimum razor that you can stake for first time: ", minSafeRazor) - if valueInWei.Cmp(minSafeRazor) < 0 { + stakerId, err := razorUtils.GetStakerId(client, address) + utils.CheckError("Error in getting stakerId: ", err) + log.Debug("ExecuteStake: Staker Id: ", stakerId) + + if valueInWei.Cmp(minSafeRazor) < 0 && stakerId == 0 { log.Fatal("The amount of razors entered is below min safe value.") } @@ -70,6 +83,7 @@ func (*UtilsStruct) ExecuteStake(flagSet *pflag.FlagSet) { Config: config, } + log.Debug("ExecuteStake: Calling Approve() for amount: ", txnArgs.Amount) approveTxnHash, err := cmdUtils.Approve(txnArgs) utils.CheckError("Approve error: ", err) @@ -78,6 +92,7 @@ func (*UtilsStruct) ExecuteStake(flagSet *pflag.FlagSet) { utils.CheckError("Error in WaitForBlockCompletion for approve: ", err) } + log.Debug("ExecuteStake: Calling StakeCoins() for amount: ", txnArgs.Amount) stakeTxnHash, err := cmdUtils.StakeCoins(txnArgs) utils.CheckError("Stake error: ", err) @@ -91,13 +106,14 @@ func (*UtilsStruct) StakeCoins(txnArgs types.TransactionOptions) (common.Hash, e if err != nil { return common.Hash{0x00}, err } + log.Debug("StakeCoins: Epoch: ", epoch) - log.Info("Sending stake transactions...") txnArgs.ContractAddress = core.StakeManagerAddress txnArgs.MethodName = "stake" txnArgs.Parameters = []interface{}{epoch, txnArgs.Amount} txnArgs.ABI = bindings.StakeManagerABI txnOpts := razorUtils.GetTxnOpts(txnArgs) + log.Debugf("Executing Stake transaction with epoch = %d, amount = %d", epoch, txnArgs.Amount) tx, err := stakeManagerUtils.Stake(txnArgs.Client, txnOpts, epoch, txnArgs.Amount) if err != nil { return common.Hash{0x00}, err @@ -111,11 +127,13 @@ func init() { var ( Amount string Address string + Password string WeiRazor bool ) stakeCmd.Flags().StringVarP(&Amount, "value", "v", "0", "amount of Razors to stake") stakeCmd.Flags().StringVarP(&Address, "address", "a", "", "address of the staker") + stakeCmd.Flags().StringVarP(&Password, "password", "", "", "password path of staker to protect the keystore") stakeCmd.Flags().BoolVarP(&WeiRazor, "weiRazor", "", false, "value can be passed in wei") amountErr := stakeCmd.MarkFlagRequired("value") diff --git a/cmd/addStake_test.go b/cmd/addStake_test.go index d87808b4..f2cd062f 100644 --- a/cmd/addStake_test.go +++ b/cmd/addStake_test.go @@ -147,6 +147,8 @@ func TestExecuteStake(t *testing.T) { approveErr error minSafeRazor *big.Int minSafeRazorErr error + stakerId uint32 + stakerIdErr error stakeTxn common.Hash stakeErr error } @@ -164,6 +166,7 @@ func TestExecuteStake(t *testing.T) { amount: big.NewInt(2000), balance: big.NewInt(10000), minSafeRazor: big.NewInt(0), + stakerId: 1, approveTxn: common.BigToHash(big.NewInt(1)), stakeTxn: common.BigToHash(big.NewInt(2)), }, @@ -179,6 +182,7 @@ func TestExecuteStake(t *testing.T) { amount: big.NewInt(2000), balance: big.NewInt(10000), minSafeRazor: big.NewInt(0), + stakerId: 1, approveTxn: common.BigToHash(big.NewInt(1)), stakeTxn: common.BigToHash(big.NewInt(2)), }, @@ -194,6 +198,7 @@ func TestExecuteStake(t *testing.T) { amount: big.NewInt(2000), balance: big.NewInt(10000), minSafeRazor: big.NewInt(0), + stakerId: 1, approveTxn: common.BigToHash(big.NewInt(1)), stakeTxn: common.BigToHash(big.NewInt(2)), }, @@ -222,6 +227,7 @@ func TestExecuteStake(t *testing.T) { amount: big.NewInt(2000), balance: big.NewInt(10000), minSafeRazor: big.NewInt(0), + stakerId: 1, approveTxn: core.NilHash, approveErr: errors.New("approve error"), stakeTxn: common.BigToHash(big.NewInt(2)), @@ -237,6 +243,7 @@ func TestExecuteStake(t *testing.T) { amount: big.NewInt(2000), balance: big.NewInt(10000), minSafeRazor: big.NewInt(0), + stakerId: 1, approveTxn: common.BigToHash(big.NewInt(1)), stakeTxn: core.NilHash, stakeErr: errors.New("stake error"), @@ -251,6 +258,7 @@ func TestExecuteStake(t *testing.T) { address: "0x000000000000000000000000000000000000dead", amount: big.NewInt(2000), minSafeRazor: big.NewInt(0), + stakerId: 1, balance: nil, balanceErr: errors.New("balance error"), approveTxn: common.BigToHash(big.NewInt(1)), @@ -259,7 +267,7 @@ func TestExecuteStake(t *testing.T) { expectedFatal: true, }, { - name: "Test 8: When stake value is less than minSafeRazor", + name: "Test 8: When stake value is less than minSafeRazor and staker has never staked", args: args{ config: config, password: "test", @@ -267,9 +275,25 @@ func TestExecuteStake(t *testing.T) { amount: big.NewInt(20), balance: big.NewInt(10000), minSafeRazor: big.NewInt(100), + stakerId: 0, }, expectedFatal: true, }, + { + name: "Test 9: When stake value is less than minSafeRazor and staker's stake is more than the minSafeRazor already", + args: args{ + config: config, + password: "test", + address: "0x000000000000000000000000000000000000dead", + amount: big.NewInt(20), + balance: big.NewInt(10000), + minSafeRazor: big.NewInt(100), + stakerId: 1, + approveTxn: common.BigToHash(big.NewInt(1)), + stakeTxn: common.BigToHash(big.NewInt(2)), + }, + expectedFatal: false, + }, } defer func() { log.ExitFunc = nil }() @@ -290,7 +314,7 @@ func TestExecuteStake(t *testing.T) { utilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet")) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) - utilsMock.On("AssignPassword").Return(tt.args.password) + utilsMock.On("AssignPassword", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.password) flagSetUtilsMock.On("GetStringAddress", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.address, tt.args.addressErr) utilsMock.On("ConnectToClient", mock.AnythingOfType("string")).Return(client) utilsMock.On("WaitForBlockCompletion", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return(nil) @@ -299,6 +323,7 @@ func TestExecuteStake(t *testing.T) { utilsMock.On("CheckAmountAndBalance", mock.AnythingOfType("*big.Int"), mock.AnythingOfType("*big.Int")).Return(tt.args.amount) utilsMock.On("CheckEthBalanceIsZero", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return() utilsPkgMock.On("GetMinSafeRazor", mock.AnythingOfType("*ethclient.Client")).Return(tt.args.minSafeRazor, tt.args.minSafeRazorErr) + utilsMock.On("GetStakerId", mock.Anything, mock.Anything).Return(tt.args.stakerId, tt.args.stakerIdErr) cmdUtilsMock.On("Approve", mock.Anything).Return(tt.args.approveTxn, tt.args.approveErr) cmdUtilsMock.On("StakeCoins", mock.Anything).Return(tt.args.stakeTxn, tt.args.stakeErr) diff --git a/cmd/approve.go b/cmd/approve.go index d0f0b2c5..2f35ae63 100644 --- a/cmd/approve.go +++ b/cmd/approve.go @@ -15,6 +15,7 @@ func (*UtilsStruct) Approve(txnArgs types.TransactionOptions) (common.Hash, erro if err != nil { return common.Hash{0x00}, err } + log.Debugf("Approve: Allowance amount: %d, Amount to get approved: %d", allowance, txnArgs.Amount) if allowance.Cmp(txnArgs.Amount) >= 0 { log.Debug("Sufficient allowance, no need to increase") return common.Hash{0x00}, nil @@ -25,6 +26,7 @@ func (*UtilsStruct) Approve(txnArgs types.TransactionOptions) (common.Hash, erro txnArgs.ABI = bindings.RAZORABI txnArgs.Parameters = []interface{}{common.HexToAddress(core.StakeManagerAddress), txnArgs.Amount} txnOpts := razorUtils.GetTxnOpts(txnArgs) + log.Debug("Executing Approve transaction with amount: ", txnArgs.Amount) txn, err := tokenManagerUtils.Approve(txnArgs.Client, txnOpts, common.HexToAddress(core.StakeManagerAddress), txnArgs.Amount) if err != nil { return common.Hash{0x00}, err diff --git a/cmd/claimBounty.go b/cmd/claimBounty.go index 8c812a2c..a4b46efb 100644 --- a/cmd/claimBounty.go +++ b/cmd/claimBounty.go @@ -3,10 +3,6 @@ package cmd import ( "errors" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/spf13/cobra" - "github.com/spf13/pflag" "math/big" "os" "razor/core" @@ -15,6 +11,11 @@ import ( "razor/path" "razor/pkg/bindings" "razor/utils" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/spf13/cobra" + "github.com/spf13/pflag" ) var claimBountyCmd = &cobra.Command{ @@ -36,20 +37,25 @@ func initialiseClaimBounty(cmd *cobra.Command, args []string) { func (*UtilsStruct) ExecuteClaimBounty(flagSet *pflag.FlagSet) { config, err := cmdUtils.GetConfigData() utils.CheckError("Error in getting config: ", err) + log.Debugf("ExecuteClaimBounty: config: %+v", config) client := razorUtils.ConnectToClient(config.Provider) address, err := flagSetUtils.GetStringAddress(flagSet) utils.CheckError("Error in getting address: ", err) + log.Debug("ExecuteClaimBounty: Address: ", address) logger.SetLoggerParameters(client, address) + log.Debug("Checking to assign log file...") razorUtils.AssignLogFile(flagSet) - password := razorUtils.AssignPassword() + log.Debug("Getting password...") + password := razorUtils.AssignPassword(flagSet) if utilsInterface.IsFlagPassed("bountyId") { bountyId, err := flagSetUtils.GetUint32BountyId(flagSet) utils.CheckError("Error in getting bountyId: ", err) + log.Debug("ExecuteClaimBounty: BountyId: ", bountyId) redeemBountyInput := types.RedeemBountyInput{ Address: address, @@ -57,6 +63,7 @@ func (*UtilsStruct) ExecuteClaimBounty(flagSet *pflag.FlagSet) { BountyId: bountyId, } + log.Debugf("ExecuteClaimBounty: Calling ClaimBounty() with arguments redeem bounty input: %+v", redeemBountyInput) txn, err := cmdUtils.ClaimBounty(config, client, redeemBountyInput) utils.CheckError("ClaimBounty error: ", err) @@ -65,6 +72,7 @@ func (*UtilsStruct) ExecuteClaimBounty(flagSet *pflag.FlagSet) { utils.CheckError("Error in WaitForBlockCompletion for claimBounty: ", err) } } else { + log.Debug("ExecuteClaimBounty: Calling HandleClaimBounty()") err := cmdUtils.HandleClaimBounty(client, config, types.Account{ Address: address, Password: password, @@ -80,11 +88,15 @@ func (*UtilsStruct) HandleClaimBounty(client *ethclient.Client, config types.Con if err != nil { return err } + log.Debug("HandleClaimBounty: Dispute data file path: ", disputeFilePath) if _, err := path.OSUtilsInterface.Stat(disputeFilePath); !errors.Is(err, os.ErrNotExist) { + log.Debug("Fetching the dispute data from dispute data file...") disputeData, err = razorUtils.ReadFromDisputeJsonFile(disputeFilePath) if err != nil { return err } + + log.Debugf("HandleClaimBounty: DisputeData: %+v", disputeData) } if disputeData.BountyIdQueue == nil { @@ -96,11 +108,13 @@ func (*UtilsStruct) HandleClaimBounty(client *ethclient.Client, config types.Con log.Info("Bounty ids that needs be claimed: ", disputeData.BountyIdQueue) length := len(disputeData.BountyIdQueue) log.Info("Claiming bounty for bountyId ", disputeData.BountyIdQueue[length-1]) - claimBountyTxn, err := cmdUtils.ClaimBounty(config, client, types.RedeemBountyInput{ + redeemBountyInput := types.RedeemBountyInput{ BountyId: disputeData.BountyIdQueue[length-1], Address: account.Address, Password: account.Password, - }) + } + log.Debugf("HandleClaimBounty: Calling ClaimBounty() with arguments redeemBountyInput: %+v", redeemBountyInput) + claimBountyTxn, err := cmdUtils.ClaimBounty(config, client, redeemBountyInput) if err != nil { return err } @@ -117,6 +131,7 @@ func (*UtilsStruct) HandleClaimBounty(client *ethclient.Client, config types.Con } } + log.Debug("Saving the updated dispute data to dispute data file...") err = razorUtils.SaveDataToDisputeJsonFile(disputeFilePath, disputeData.BountyIdQueue) if err != nil { return err @@ -142,6 +157,7 @@ func (*UtilsStruct) ClaimBounty(config types.Configurations, client *ethclient.C log.Error("Error in getting epoch: ", err) return common.Hash{0x00}, err } + log.Debug("ClaimBounty: Epoch: ", epoch) callOpts := razorUtils.GetOptions() bountyLock, err := stakeManagerUtils.GetBountyLock(txnArgs.Client, &callOpts, redeemBountyInput.BountyId) @@ -149,6 +165,7 @@ func (*UtilsStruct) ClaimBounty(config types.Configurations, client *ethclient.C log.Error("Error in getting bounty lock: ", err) return core.NilHash, err } + log.Debugf("ClaimBounty: Bounty lock: %+v", bountyLock) if bountyLock.Amount.Cmp(big.NewInt(0)) == 0 { err = errors.New("bounty amount is 0") @@ -172,6 +189,7 @@ func (*UtilsStruct) ClaimBounty(config types.Configurations, client *ethclient.C txnOpts := razorUtils.GetTxnOpts(txnArgs) + log.Debug("Executing RedeemBounty transaction with bountyId: ", redeemBountyInput.BountyId) tx, err := stakeManagerUtils.RedeemBounty(txnArgs.Client, txnOpts, redeemBountyInput.BountyId) if err != nil { return core.NilHash, err @@ -183,10 +201,12 @@ func init() { rootCmd.AddCommand(claimBountyCmd) var ( Address string + Password string BountyId uint32 ) claimBountyCmd.Flags().StringVarP(&Address, "address", "a", "", "address of the staker") + claimBountyCmd.Flags().StringVarP(&Password, "password", "", "", "password path of staker to protect the keystore") claimBountyCmd.Flags().Uint32VarP(&BountyId, "bountyId", "", 0, "bountyId of the bounty hunter") addrErr := claimBountyCmd.MarkFlagRequired("address") diff --git a/cmd/claimBounty_test.go b/cmd/claimBounty_test.go index 3d2490cc..05f23f8f 100644 --- a/cmd/claimBounty_test.go +++ b/cmd/claimBounty_test.go @@ -136,7 +136,7 @@ func TestExecuteClaimBounty(t *testing.T) { utilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet")) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) - utilsMock.On("AssignPassword").Return(tt.args.password) + utilsMock.On("AssignPassword", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.password) flagSetUtilsMock.On("GetStringAddress", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.address, tt.args.addressErr) flagSetUtilsMock.On("GetUint32BountyId", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.bountyId, tt.args.bountyIdErr) utilsMock.On("ConnectToClient", mock.AnythingOfType("string")).Return(client) diff --git a/cmd/claimCommission.go b/cmd/claimCommission.go index 6ddd5d60..155d4aee 100644 --- a/cmd/claimCommission.go +++ b/cmd/claimCommission.go @@ -2,13 +2,15 @@ package cmd import ( - "github.com/spf13/pflag" + "math/big" "razor/core" "razor/core/types" "razor/logger" "razor/pkg/bindings" "razor/utils" + "github.com/spf13/pflag" + "github.com/spf13/cobra" ) @@ -27,51 +29,69 @@ Example: func (*UtilsStruct) ClaimCommission(flagSet *pflag.FlagSet) { config, err := cmdUtils.GetConfigData() utils.CheckError("Error in getting config: ", err) + log.Debugf("ClaimCommission: Config: %+v", config) client := razorUtils.ConnectToClient(config.Provider) address, err := flagSetUtils.GetStringAddress(flagSet) utils.CheckError("Error in getting address: ", err) + log.Debug("ClaimCommission: Address: ", address) logger.SetLoggerParameters(client, address) + log.Debug("Checking to assign log file...") razorUtils.AssignLogFile(flagSet) - password := razorUtils.AssignPassword() + log.Debug("Getting password...") + password := razorUtils.AssignPassword(flagSet) razorUtils.CheckEthBalanceIsZero(client, address) - txnOpts := razorUtils.GetTxnOpts(types.TransactionOptions{ - Client: client, - AccountAddress: address, - Password: password, - ChainId: core.ChainId, - Config: config, - ContractAddress: core.StakeManagerAddress, - MethodName: "claimStakerReward", - Parameters: []interface{}{}, - ABI: bindings.StakeManagerABI, - }) - - log.Info("Claiming commission") - - txn, err := stakeManagerUtils.ClaimStakeReward(client, txnOpts) - if err != nil { - log.Fatal("Error in claiming stake reward: ", err) + stakerId, err := razorUtils.GetStakerId(client, address) + utils.CheckError("Error in getting stakerId: ", err) + log.Debug("ClaimCommission: Staker Id: ", stakerId) + callOpts := razorUtils.GetOptions() + + stakerInfo, err := stakeManagerUtils.StakerInfo(client, &callOpts, stakerId) + utils.CheckError("Error in getting stakerInfo: ", err) + log.Debugf("ClaimCommission: Staker Info: %+v", stakerInfo) + + if stakerInfo.StakerReward.Cmp(big.NewInt(0)) > 0 { + txnOpts := razorUtils.GetTxnOpts(types.TransactionOptions{ + Client: client, + AccountAddress: address, + Password: password, + ChainId: core.ChainId, + Config: config, + ContractAddress: core.StakeManagerAddress, + MethodName: "claimStakerReward", + Parameters: []interface{}{}, + ABI: bindings.StakeManagerABI, + }) + + log.Info("Claiming commission...") + + log.Debug("Executing ClaimStakeReward transaction...") + txn, err := stakeManagerUtils.ClaimStakeReward(client, txnOpts) + utils.CheckError("Error in claiming stake reward: ", err) + + err = razorUtils.WaitForBlockCompletion(client, transactionUtils.Hash(txn).String()) + utils.CheckError("Error in WaitForBlockCompletion for claimCommission: ", err) + } else { + log.Error("no commission to claim") + return } - - err = razorUtils.WaitForBlockCompletion(client, transactionUtils.Hash(txn).String()) - utils.CheckError("Error in WaitForBlockCompletion for claimCommission: ", err) - } func init() { rootCmd.AddCommand(claimCommissionCmd) var ( - Address string + Address string + Password string ) claimCommissionCmd.Flags().StringVarP(&Address, "address", "a", "", "address of the staker") + claimCommissionCmd.Flags().StringVarP(&Password, "password", "", "", "password path of staker to protect the keystore") addrErr := claimCommissionCmd.MarkFlagRequired("address") utils.CheckError("Address error: ", addrErr) diff --git a/cmd/claimCommission_test.go b/cmd/claimCommission_test.go index 8c5fe102..1db00526 100644 --- a/cmd/claimCommission_test.go +++ b/cmd/claimCommission_test.go @@ -20,19 +20,25 @@ import ( func TestUtilsStruct_ClaimCommission(t *testing.T) { var client *ethclient.Client var flagSet *pflag.FlagSet + var callOpts bind.CallOpts privateKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) txnOpts, _ := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(31337)) type args struct { - config types.Configurations - configErr error - password string - address string - addressErr error - txn *Types.Transaction - err error - hash common.Hash + config types.Configurations + configErr error + password string + address string + addressErr error + stakerInfo types.Staker + stakerInfoErr error + stakerId uint32 + stakerIdErr error + callOpts bind.CallOpts + txn *Types.Transaction + err error + hash common.Hash } tests := []struct { name string @@ -43,20 +49,37 @@ func TestUtilsStruct_ClaimCommission(t *testing.T) { name: "Test 1: When ClaimStakeReward runs successfully", args: args{ config: types.Configurations{}, - password: "test", - address: "0x000000000000000000000000000000000000dead", - txn: &Types.Transaction{}, + stakerId: 1, + callOpts: bind.CallOpts{ + Pending: false, + From: common.HexToAddress("0x000000000000000000000000000000000000dead"), + BlockNumber: big.NewInt(1), + }, + stakerInfo: types.Staker{ + StakerReward: big.NewInt(100), + }, + stakerInfoErr: nil, + password: "test", + address: "0x000000000000000000000000000000000000dead", + txn: &Types.Transaction{}, }, expectedFatal: false, }, { - name: "Test 2: When ClaimStakeReward fails", + name: "Test 2: When there is an error in fetching staker id", args: args{ - config: types.Configurations{}, + config: types.Configurations{}, + stakerId: 0, + stakerIdErr: errors.New("error in getting staker id"), + stakerInfo: types.Staker{ + StakerReward: big.NewInt(0), + }, + callOpts: bind.CallOpts{ + Pending: false, + From: common.HexToAddress("0x000000000000000000000000000000000000dead"), + BlockNumber: big.NewInt(1), + }, password: "test", - address: "0x000000000000000000000000000000000000dead", - txn: nil, - err: errors.New("error in claiming stake reward"), }, expectedFatal: true, }, @@ -66,9 +89,109 @@ func TestUtilsStruct_ClaimCommission(t *testing.T) { config: types.Configurations{}, configErr: errors.New("error in fetching config"), address: "0x000000000000000000000000000000000000dead", + stakerInfo: types.Staker{ + StakerReward: big.NewInt(0), + }, + callOpts: bind.CallOpts{ + Pending: false, + From: common.HexToAddress("0x000000000000000000000000000000000000dead"), + BlockNumber: big.NewInt(1), + }, + }, + + expectedFatal: true, + }, + { + name: "Test 4: When there is an error in fetching stakerInfo", + args: args{ + config: types.Configurations{}, + stakerInfo: types.Staker{ + Address: common.Address{}, + TokenAddress: common.Address{}, + Stake: nil, + StakerReward: big.NewInt(0), + }, + stakerInfoErr: errors.New("error in fetching staker info"), + callOpts: bind.CallOpts{ + Pending: false, + From: common.HexToAddress("0x000000000000000000000000000000000000dead"), + BlockNumber: big.NewInt(1), + }, + stakerId: 1, + stakerIdErr: nil, + password: "test", }, expectedFatal: true, }, + { + name: "Test 5: When there is an error in claiming stake reward", + args: args{ + config: types.Configurations{}, + stakerInfo: types.Staker{ + Address: common.Address{}, + TokenAddress: common.Address{}, + Stake: nil, + StakerReward: big.NewInt(100), + }, + stakerInfoErr: nil, + callOpts: bind.CallOpts{ + Pending: false, + From: common.HexToAddress("0x000000000000000000000000000000000000dead"), + BlockNumber: big.NewInt(1), + }, + stakerId: 1, + stakerIdErr: nil, + password: "test", + err: errors.New("error in claiming stake reward"), + }, + expectedFatal: true, + }, + { + name: "Test 6: When there is an error in mining block", + args: args{ + config: types.Configurations{}, + stakerInfo: types.Staker{ + Address: common.Address{}, + TokenAddress: common.Address{}, + Stake: nil, + StakerReward: big.NewInt(100), + }, + stakerInfoErr: nil, + callOpts: bind.CallOpts{ + Pending: false, + From: common.HexToAddress("0x000000000000000000000000000000000000dead"), + BlockNumber: big.NewInt(1), + }, + stakerId: 1, + stakerIdErr: nil, + password: "test", + err: errors.New("error in wait for blockCompletion for claim commission"), + }, + expectedFatal: true, + }, + { + name: "Test 7: When there is no commission to claim", + args: args{ + config: types.Configurations{}, + stakerInfo: types.Staker{ + Address: common.Address{}, + TokenAddress: common.Address{}, + Stake: nil, + StakerReward: big.NewInt(0), + }, + stakerInfoErr: nil, + callOpts: bind.CallOpts{ + Pending: false, + From: common.HexToAddress("0x000000000000000000000000000000000000dead"), + BlockNumber: big.NewInt(1), + }, + stakerId: 1, + stakerIdErr: nil, + password: "test", + err: errors.New("no commission to claim"), + }, + expectedFatal: false, + }, } defer func() { log.ExitFunc = nil }() @@ -93,14 +216,19 @@ func TestUtilsStruct_ClaimCommission(t *testing.T) { transactionUtils = transactionUtilsMock utilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet")) - flagSetUtilsMock.On("GetStringAddress", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.address, tt.args.addressErr) - cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) - utilsMock.On("AssignPassword").Return(tt.args.password) + utilsMock.On("GetStakerId", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return(tt.args.stakerId, tt.args.stakerIdErr) + utilsMock.On("GetOptions").Return(callOpts) + utilsMock.On("AssignPassword", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.password) utilsMock.On("ConnectToClient", mock.AnythingOfType("string")).Return(client) utilsMock.On("CheckEthBalanceIsZero", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return() utilsMock.On("GetTxnOpts", mock.AnythingOfType("types.TransactionOptions")).Return(txnOpts) - stakeManagerUtilsMock.On("ClaimStakeReward", mock.AnythingOfType("*ethclient.Client"), mock.Anything).Return(tt.args.txn, tt.args.err) utilsMock.On("WaitForBlockCompletion", mock.AnythingOfType("*ethclient.Client"), mock.Anything).Return(nil) + + stakeManagerUtilsMock.On("StakerInfo", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("*bind.CallOpts"), mock.AnythingOfType("uint32")).Return(tt.args.stakerInfo, tt.args.stakerInfoErr) + stakeManagerUtilsMock.On("ClaimStakeReward", mock.AnythingOfType("*ethclient.Client"), mock.Anything).Return(tt.args.txn, tt.args.err) + + flagSetUtilsMock.On("GetStringAddress", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.address, tt.args.addressErr) + cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) transactionUtilsMock.On("Hash", mock.Anything).Return(tt.args.hash) utils := &UtilsStruct{} diff --git a/cmd/cmd-utils.go b/cmd/cmd-utils.go index c9779ebf..6c105446 100644 --- a/cmd/cmd-utils.go +++ b/cmd/cmd-utils.go @@ -74,6 +74,7 @@ func (*UtilsStruct) AssignAmountInWei(flagSet *pflag.FlagSet) (*big.Int, error) log.Error("Error in reading value: ", err) return nil, err } + log.Debug("AssignAmountInWei: Amount: ", amount) _amount, ok := new(big.Int).SetString(amount, 10) if !ok { @@ -87,6 +88,7 @@ func (*UtilsStruct) AssignAmountInWei(flagSet *pflag.FlagSet) (*big.Int, error) return nil, err } if weiRazorPassed { + log.Debug("weiRazor flag is passed as true, considering teh value input in wei") amountInWei = _amount } } else { diff --git a/cmd/collectionList.go b/cmd/collectionList.go index 780502f3..239dc9a2 100644 --- a/cmd/collectionList.go +++ b/cmd/collectionList.go @@ -33,10 +33,12 @@ func initialiseCollectionList(cmd *cobra.Command, args []string) { func (*UtilsStruct) ExecuteCollectionList(flagSet *pflag.FlagSet) { config, err := cmdUtils.GetConfigData() utils.CheckError("Error in getting config: ", err) + log.Debugf("ExecuteCollectionList: Config: %+v", config) client := razorUtils.ConnectToClient(config.Provider) logger.SetLoggerParameters(client, "") + log.Debug("Calling GetCollectionList()") err = cmdUtils.GetCollectionList(client) utils.CheckError("Error in getting collection list: ", err) } @@ -44,6 +46,7 @@ func (*UtilsStruct) ExecuteCollectionList(flagSet *pflag.FlagSet) { //This function provides the list of all collections with their name, power, ID etc. func (*UtilsStruct) GetCollectionList(client *ethclient.Client) error { collections, err := razorUtils.GetCollections(client) + log.Debugf("GetCollectionList: Collections: %+v", collections) if err != nil { return err diff --git a/cmd/commit.go b/cmd/commit.go index 252295ae..b190a118 100644 --- a/cmd/commit.go +++ b/cmd/commit.go @@ -20,14 +20,17 @@ If the previous epoch doesn't contain any medians, then the value is fetched fro */ func (*UtilsStruct) GetSalt(client *ethclient.Client, epoch uint32) ([32]byte, error) { previousEpoch := epoch - 1 + log.Debug("GetSalt: Previous epoch: ", previousEpoch) numProposedBlock, err := utils.UtilsInterface.GetNumberOfProposedBlocks(client, previousEpoch) if err != nil { return [32]byte{}, err } + log.Debug("GetSalt: Number of proposed blocks: ", numProposedBlock) blockIndexedToBeConfirmed, err := utils.UtilsInterface.GetBlockIndexToBeConfirmed(client) if err != nil { return [32]byte{}, err } + log.Debug("GetSalt: Block Index to be confirmed: ", blockIndexedToBeConfirmed) if numProposedBlock == 0 || (numProposedBlock > 0 && blockIndexedToBeConfirmed < 0) { return utils.VoteManagerInterface.GetSaltFromBlockchain(client) } @@ -35,10 +38,13 @@ func (*UtilsStruct) GetSalt(client *ethclient.Client, epoch uint32) ([32]byte, e if err != nil { return [32]byte{}, errors.New("Error in getting blockId: " + err.Error()) } + log.Debug("GetSalt: Block Id: ", blockId) previousBlock, err := utils.UtilsInterface.GetProposedBlock(client, previousEpoch, blockId) if err != nil { return [32]byte{}, errors.New("Error in getting previous block: " + err.Error()) } + log.Debug("GetSalt: PreviousBlock: ", previousBlock) + log.Debugf("GetSalt: Calling CalculateSalt() with arguments previous epoch = %d, previous block medians = %s", previousEpoch, previousBlock.Medians) return utils.UtilsInterface.CalculateSalt(previousEpoch, previousBlock.Medians), nil } @@ -51,14 +57,18 @@ func (*UtilsStruct) HandleCommitState(client *ethclient.Client, epoch uint32, se if err != nil { return types.CommitData{}, err } - + log.Debug("HandleCommitState: Number of active collections: ", numActiveCollections) + log.Debugf("HandleCommitState: Calling GetAssignedCollections() with arguments number of active collections = %d, seed = %v", numActiveCollections, seed) assignedCollections, seqAllottedCollections, err := utils.UtilsInterface.GetAssignedCollections(client, numActiveCollections, seed) if err != nil { return types.CommitData{}, err } var leavesOfTree []*big.Int + log.Debug("Iterating over all the collections...") for i := 0; i < int(numActiveCollections); i++ { + log.Debug("HandleCommitState: Iterating index: ", i) + log.Debug("HandleCommitState: Is the collection assigned: ", assignedCollections[i]) if assignedCollections[i] { collectionId, err := utils.UtilsInterface.GetCollectionIdFromIndex(client, uint16(i)) if err != nil { @@ -69,17 +79,19 @@ func (*UtilsStruct) HandleCommitState(client *ethclient.Client, epoch uint32, se return types.CommitData{}, err } if rogueData.IsRogue && utils.Contains(rogueData.RogueMode, "commit") { + log.Warn("YOU ARE COMMITTING VALUES IN ROGUE MODE, THIS CAN INCUR PENALTIES!") collectionData = razorUtils.GetRogueRandomValue(100000) + log.Debug("HandleCommitState: Collection data in rogue mode: ", collectionData) } - log.Debugf("Data of collection %d:%s", collectionId, collectionData) + log.Debugf("HandleCommitState: Data of collection %d: %s", collectionId, collectionData) leavesOfTree = append(leavesOfTree, collectionData) } else { leavesOfTree = append(leavesOfTree, big.NewInt(0)) } } - log.Debug("Assigned Collections: ", assignedCollections) - log.Debug("SeqAllottedCollections: ", seqAllottedCollections) - log.Debug("Leaves: ", leavesOfTree) + log.Debug("HandleCommitState: Assigned Collections: ", assignedCollections) + log.Debug("HandleCommitState: SeqAllottedCollections: ", seqAllottedCollections) + log.Debug("HandleCommitState: Leaves: ", leavesOfTree) return types.CommitData{ AssignedCollections: assignedCollections, SeqAllottedCollections: seqAllottedCollections, @@ -114,6 +126,7 @@ func (*UtilsStruct) Commit(client *ethclient.Client, config types.Configurations log.Debugf("Committing: epoch: %d, commitment: %s, seed: %s, account: %s", epoch, "0x"+hex.EncodeToString(commitment), "0x"+hex.EncodeToString(seed), account.Address) log.Info("Commitment sent...") + log.Debugf("Executing Commit transaction with epoch = %d, commitmentToSend = %v", epoch, commitmentToSend) txn, err := voteManagerUtils.Commit(client, txnOpts, epoch, commitmentToSend) if err != nil { return core.NilHash, err diff --git a/cmd/config-utils.go b/cmd/config-utils.go index 33177bc0..17d533e2 100644 --- a/cmd/config-utils.go +++ b/cmd/config-utils.go @@ -3,7 +3,9 @@ package cmd import ( "github.com/spf13/viper" + "razor/core" "razor/core/types" + "razor/utils" "strings" ) @@ -16,6 +18,7 @@ func (*UtilsStruct) GetConfigData() (types.Configurations, error) { WaitTime: 0, LogLevel: "", GasLimitMultiplier: 0, + RPCTimeout: 0, } provider, err := cmdUtils.GetProvider() @@ -46,6 +49,10 @@ func (*UtilsStruct) GetConfigData() (types.Configurations, error) { if err != nil { return config, err } + rpcTimeout, err := cmdUtils.GetRPCTimeout() + if err != nil { + return config, err + } config.Provider = provider config.GasMultiplier = gasMultiplier config.BufferPercent = bufferPercent @@ -53,6 +60,8 @@ func (*UtilsStruct) GetConfigData() (types.Configurations, error) { config.GasPrice = gasPrice config.LogLevel = logLevel config.GasLimitMultiplier = gasLimit + config.RPCTimeout = rpcTimeout + utils.RPCTimeout = rpcTimeout return config, nil } @@ -61,10 +70,15 @@ func (*UtilsStruct) GetConfigData() (types.Configurations, error) { func (*UtilsStruct) GetProvider() (string, error) { provider, err := flagSetUtils.GetRootStringProvider() if err != nil { - return "", err + return core.DefaultProvider, err } if provider == "" { - provider = viper.GetString("provider") + if viper.IsSet("provider") { + provider = viper.GetString("provider") + } else { + provider = core.DefaultProvider + log.Debug("Provider is not set, taking its default value ", provider) + } } if !strings.HasPrefix(provider, "https") { log.Warn("You are not using a secure RPC URL. Switch to an https URL instead to be safe.") @@ -76,10 +90,15 @@ func (*UtilsStruct) GetProvider() (string, error) { func (*UtilsStruct) GetMultiplier() (float32, error) { gasMultiplier, err := flagSetUtils.GetRootFloat32GasMultiplier() if err != nil { - return 1, err + return float32(core.DefaultGasMultiplier), err } if gasMultiplier == -1 { - gasMultiplier = float32(viper.GetFloat64("gasmultiplier")) + if viper.IsSet("gasmultiplier") { + gasMultiplier = float32(viper.GetFloat64("gasmultiplier")) + } else { + gasMultiplier = float32(core.DefaultGasMultiplier) + log.Debug("GasMultiplier is not set, taking its default value ", gasMultiplier) + } } return gasMultiplier, nil } @@ -88,10 +107,15 @@ func (*UtilsStruct) GetMultiplier() (float32, error) { func (*UtilsStruct) GetBufferPercent() (int32, error) { bufferPercent, err := flagSetUtils.GetRootInt32Buffer() if err != nil { - return 30, err + return int32(core.DefaultBufferPercent), err } if bufferPercent == 0 { - bufferPercent = viper.GetInt32("buffer") + if viper.IsSet("buffer") { + bufferPercent = viper.GetInt32("buffer") + } else { + bufferPercent = int32(core.DefaultBufferPercent) + log.Debug("BufferPercent is not set, taking its default value ", bufferPercent) + } } return bufferPercent, nil } @@ -100,10 +124,15 @@ func (*UtilsStruct) GetBufferPercent() (int32, error) { func (*UtilsStruct) GetWaitTime() (int32, error) { waitTime, err := flagSetUtils.GetRootInt32Wait() if err != nil { - return 3, err + return int32(core.DefaultWaitTime), err } if waitTime == -1 { - waitTime = viper.GetInt32("wait") + if viper.IsSet("wait") { + waitTime = viper.GetInt32("wait") + } else { + waitTime = int32(core.DefaultWaitTime) + log.Debug("WaitTime is not set, taking its default value ", waitTime) + } } return waitTime, nil } @@ -112,10 +141,16 @@ func (*UtilsStruct) GetWaitTime() (int32, error) { func (*UtilsStruct) GetGasPrice() (int32, error) { gasPrice, err := flagSetUtils.GetRootInt32GasPrice() if err != nil { - return 0, err + return int32(core.DefaultGasPrice), err } if gasPrice == -1 { - gasPrice = viper.GetInt32("gasprice") + if viper.IsSet("gasprice") { + gasPrice = viper.GetInt32("gasprice") + } else { + gasPrice = int32(core.DefaultGasPrice) + log.Debug("GasPrice is not set, taking its default value ", gasPrice) + + } } return gasPrice, nil } @@ -124,10 +159,15 @@ func (*UtilsStruct) GetGasPrice() (int32, error) { func (*UtilsStruct) GetLogLevel() (string, error) { logLevel, err := flagSetUtils.GetRootStringLogLevel() if err != nil { - return "", err + return core.DefaultLogLevel, err } if logLevel == "" { - logLevel = viper.GetString("logLevel") + if viper.IsSet("logLevel") { + logLevel = viper.GetString("logLevel") + } else { + logLevel = core.DefaultLogLevel + log.Debug("LogLevel is not set, taking its default value ", logLevel) + } } return logLevel, nil } @@ -136,10 +176,32 @@ func (*UtilsStruct) GetLogLevel() (string, error) { func (*UtilsStruct) GetGasLimit() (float32, error) { gasLimit, err := flagSetUtils.GetRootFloat32GasLimit() if err != nil { - return -1, err + return float32(core.DefaultGasLimit), err } if gasLimit == -1 { - gasLimit = float32(viper.GetFloat64("gasLimit")) + if viper.IsSet("gasLimit") { + gasLimit = float32(viper.GetFloat64("gasLimit")) + } else { + gasLimit = float32(core.DefaultGasLimit) + log.Debug("GasLimit is not set, taking its default value ", gasLimit) + } } return gasLimit, nil } + +//This function returns the RPC timeout +func (*UtilsStruct) GetRPCTimeout() (int64, error) { + rpcTimeout, err := flagSetUtils.GetRootInt64RPCTimeout() + if err != nil { + return int64(core.DefaultRPCTimeout), err + } + if rpcTimeout == 0 { + if viper.IsSet("rpcTimeout") { + rpcTimeout = viper.GetInt64("rpcTimeout") + } else { + rpcTimeout = int64(core.DefaultRPCTimeout) + log.Debug("RPCTimeout is not set, taking its default value ", rpcTimeout) + } + } + return rpcTimeout, nil +} diff --git a/cmd/config-utils_test.go b/cmd/config-utils_test.go index 8a28fdb1..957329c4 100644 --- a/cmd/config-utils_test.go +++ b/cmd/config-utils_test.go @@ -16,6 +16,7 @@ func TestGetConfigData(t *testing.T) { WaitTime: 0, LogLevel: "", GasLimitMultiplier: 0, + RPCTimeout: 0, } configData := types.Configurations{ @@ -25,6 +26,7 @@ func TestGetConfigData(t *testing.T) { WaitTime: 1, LogLevel: "debug", GasLimitMultiplier: 3, + RPCTimeout: 10, } type args struct { @@ -41,6 +43,8 @@ func TestGetConfigData(t *testing.T) { logLevel string logLevelErr error gasLimit float32 + rpcTimeout int64 + rpcTimeoutErr error gasLimitErr error } tests := []struct { @@ -58,6 +62,7 @@ func TestGetConfigData(t *testing.T) { waitTime: 1, logLevel: "debug", gasLimit: 3, + rpcTimeout: 10, }, want: configData, wantErr: nil, @@ -118,6 +123,14 @@ func TestGetConfigData(t *testing.T) { want: config, wantErr: errors.New("gasLimit error"), }, + { + name: "Test 9: When there is an error in getting rpcTimeout", + args: args{ + rpcTimeoutErr: errors.New("rpcTimeout error"), + }, + want: config, + wantErr: errors.New("rpcTimeout error"), + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -131,6 +144,7 @@ func TestGetConfigData(t *testing.T) { cmdUtilsMock.On("GetLogLevel").Return(tt.args.logLevel, tt.args.logLevelErr) cmdUtilsMock.On("GetGasLimit").Return(tt.args.gasLimit, tt.args.gasLimitErr) cmdUtilsMock.On("GetBufferPercent").Return(tt.args.bufferPercent, tt.args.bufferPercentErr) + cmdUtilsMock.On("GetRPCTimeout").Return(tt.args.rpcTimeout, tt.args.rpcTimeoutErr) utils := &UtilsStruct{} @@ -176,7 +190,7 @@ func TestGetBufferPercent(t *testing.T) { args: args{ bufferPercent: 0, }, - want: 0, + want: 20, wantErr: nil, }, { @@ -184,7 +198,7 @@ func TestGetBufferPercent(t *testing.T) { args: args{ bufferPercentErr: errors.New("bufferPercent error"), }, - want: 30, + want: 20, wantErr: errors.New("bufferPercent error"), }, } @@ -236,7 +250,7 @@ func TestGetGasLimit(t *testing.T) { args: args{ gasLimit: -1, }, - want: 0, + want: 2, wantErr: nil, }, { @@ -244,7 +258,7 @@ func TestGetGasLimit(t *testing.T) { args: args{ gasLimitErr: errors.New("gasLimit error"), }, - want: -1, + want: 2, wantErr: errors.New("gasLimit error"), }, } @@ -297,7 +311,7 @@ func TestGetGasPrice(t *testing.T) { args: args{ gasPrice: -1, }, - want: 0, + want: 1, wantErr: nil, }, { @@ -305,7 +319,7 @@ func TestGetGasPrice(t *testing.T) { args: args{ gasPriceErr: errors.New("gasPrice error"), }, - want: 0, + want: 1, wantErr: errors.New("gasPrice error"), }, } @@ -419,7 +433,7 @@ func TestGetMultiplier(t *testing.T) { args: args{ gasMultiplier: -1, }, - want: 0, + want: 1, wantErr: nil, }, { @@ -488,15 +502,15 @@ func TestGetProvider(t *testing.T) { args: args{ providerErr: errors.New("provider error"), }, - want: "", + want: "http://127.0.0.1:8545", wantErr: errors.New("provider error"), }, { - name: "Test 2: When provider is nil", + name: "Test 4: When provider is nil", args: args{ provider: "", }, - want: "", + want: "http://127.0.0.1:8545", wantErr: nil, }, } @@ -549,7 +563,7 @@ func TestGetWaitTime(t *testing.T) { args: args{ waitTime: -1, }, - want: 0, + want: 1, wantErr: nil, }, { @@ -557,7 +571,7 @@ func TestGetWaitTime(t *testing.T) { args: args{ waitTimeErr: errors.New("waitTime error"), }, - want: 3, + want: 1, wantErr: errors.New("waitTime error"), }, } @@ -584,3 +598,63 @@ func TestGetWaitTime(t *testing.T) { }) } } + +func TestGetRPCTimeout(t *testing.T) { + type args struct { + rpcTimeout int64 + rpcTimeoutErr error + } + tests := []struct { + name string + args args + want int64 + wantErr error + }{ + { + name: "Test 1: When getRPCTimeout function executes successfully", + args: args{ + rpcTimeout: 12, + }, + want: 12, + wantErr: nil, + }, + { + name: "Test 2: When rpcTimeout is 0", + args: args{ + rpcTimeout: 0, + }, + want: 10, + wantErr: nil, + }, + { + name: "Test 3: When there is an error in getting rpcTimeout", + args: args{ + rpcTimeoutErr: errors.New("rpcTimeout error"), + }, + want: 10, + wantErr: errors.New("rpcTimeout error"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + flagSetUtilsMock := new(mocks.FlagSetInterface) + flagSetUtils = flagSetUtilsMock + + flagSetUtilsMock.On("GetRootInt64RPCTimeout").Return(tt.args.rpcTimeout, tt.args.rpcTimeoutErr) + utils := &UtilsStruct{} + got, err := utils.GetRPCTimeout() + if got != tt.want { + t.Errorf("getRPCTimeout() got = %v, want %v", got, tt.want) + } + if err == nil || tt.wantErr == nil { + if err != tt.wantErr { + t.Errorf("Error for getRPCTimeout function, got = %v, want = %v", err, tt.wantErr) + } + } else { + if err.Error() != tt.wantErr.Error() { + t.Errorf("Error for getRPCTimeout function, got = %v, want = %v", err, tt.wantErr) + } + } + }) + } +} diff --git a/cmd/confirm.go b/cmd/confirm.go index d3344acd..a7014da6 100644 --- a/cmd/confirm.go +++ b/cmd/confirm.go @@ -15,12 +15,14 @@ func (*UtilsStruct) ClaimBlockReward(options types.TransactionOptions) (common.H log.Error("Error in getting epoch: ", err) return core.NilHash, err } + log.Debug("ClaimBlockReward: Epoch: ", epoch) sortedProposedBlockIds, err := razorUtils.GetSortedProposedBlockIds(options.Client, epoch) if err != nil { log.Error("Error in getting sortedProposedBlockIds: ", err) return core.NilHash, err } + log.Debug("ClaimBlockReward: Sorted proposed block Ids: ", sortedProposedBlockIds) if sortedProposedBlockIds == nil { log.Debug("No blocks proposed in this epoch") @@ -32,16 +34,19 @@ func (*UtilsStruct) ClaimBlockReward(options types.TransactionOptions) (common.H log.Error("Error in getting stakerId: ", err) return core.NilHash, err } + log.Debug("ClaimBlockReward: Staker Id: ", stakerID) selectedProposedBlock, err := razorUtils.GetProposedBlock(options.Client, epoch, sortedProposedBlockIds[0]) if err != nil { log.Error("Error in getting selectedProposedBlock: ", err) return core.NilHash, err } + log.Debug("ClaimBlockReward: Selected proposed block: ", selectedProposedBlock) if selectedProposedBlock.ProposerId == stakerID { log.Info("Claiming block reward...") txnOpts := razorUtils.GetTxnOpts(options) + log.Debug("Executing ClaimBlockReward transaction...") txn, err := blockManagerUtils.ClaimBlockReward(options.Client, txnOpts) if err != nil { log.Error("Error in claiming block reward: ", err) diff --git a/cmd/contractAddresses.go b/cmd/contractAddresses.go index 5123e658..43c6c730 100644 --- a/cmd/contractAddresses.go +++ b/cmd/contractAddresses.go @@ -23,6 +23,7 @@ func initialiseContractAddresses(cmd *cobra.Command, args []string) { //This function sets the flag appropriatley and executes the ContractAddresses function func (*UtilsStruct) ExecuteContractAddresses(flagSet *pflag.FlagSet) { + log.Debug("Checking to assign log file...") razorUtils.AssignLogFile(flagSet) fmt.Println("The contract addresses are: ") cmdUtils.ContractAddresses() diff --git a/cmd/create.go b/cmd/create.go index f7efa29a..6aab759e 100644 --- a/cmd/create.go +++ b/cmd/create.go @@ -28,13 +28,15 @@ func initialiseCreate(cmd *cobra.Command, args []string) { //This function sets the flags appropriately and executes the Create function func (*UtilsStruct) ExecuteCreate(flagSet *pflag.FlagSet) { + log.Debug("Checking to assign log file...") razorUtils.AssignLogFile(flagSet) log.Info("The password should be of minimum 8 characters containing least 1 uppercase, lowercase, digit and special character.") - password := razorUtils.AssignPassword() + password := razorUtils.AssignPassword(flagSet) + log.Debug("ExecuteCreate: Calling Create() with argument as input password") account, err := cmdUtils.Create(password) utils.CheckError("Create error: ", err) - log.Info("Account address: ", account.Address) - log.Info("Keystore Path: ", account.URL) + log.Info("ExecuteCreate: Account address: ", account.Address) + log.Info("ExecuteCreate: Keystore Path: ", account.URL) } //This function is used to create the new account @@ -44,6 +46,7 @@ func (*UtilsStruct) Create(password string) (accounts.Account, error) { log.Error("Error in fetching .razor directory") return accounts.Account{Address: common.Address{0x00}}, err } + log.Debug("Create: .razor directory path: ", razorPath) keystorePath := path.Join(razorPath, "keystore_files") account := razorAccounts.AccountUtilsInterface.CreateAccount(keystorePath, password) return account, nil @@ -51,4 +54,10 @@ func (*UtilsStruct) Create(password string) (accounts.Account, error) { func init() { rootCmd.AddCommand(createCmd) + + var ( + Password string + ) + + createCmd.Flags().StringVarP(&Password, "password", "", "", "password file path to protect the keystore") } diff --git a/cmd/createCollection.go b/cmd/createCollection.go index bd35314c..33d8ed11 100644 --- a/cmd/createCollection.go +++ b/cmd/createCollection.go @@ -2,15 +2,16 @@ package cmd import ( - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/spf13/cobra" - "github.com/spf13/pflag" "razor/core" "razor/core/types" "razor/logger" "razor/pkg/bindings" "razor/utils" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/spf13/cobra" + "github.com/spf13/pflag" ) var createCollectionCmd = &cobra.Command{ @@ -36,6 +37,7 @@ func initialiseCreateCollection(cmd *cobra.Command, args []string) { func (*UtilsStruct) ExecuteCreateCollection(flagSet *pflag.FlagSet) { config, err := cmdUtils.GetConfigData() utils.CheckError("Error in getting config: ", err) + log.Debugf("ExecuteCreateCollection: Config: %+v", config) client := razorUtils.ConnectToClient(config.Provider) @@ -43,9 +45,11 @@ func (*UtilsStruct) ExecuteCreateCollection(flagSet *pflag.FlagSet) { utils.CheckError("Error in getting address: ", err) logger.SetLoggerParameters(client, address) + log.Debug("Checking to assign log file...") razorUtils.AssignLogFile(flagSet) - password := razorUtils.AssignPassword() + log.Debug("Getting password...") + password := razorUtils.AssignPassword(flagSet) name, err := flagSetUtils.GetStringName(flagSet) utils.CheckError("Error in getting name: ", err) @@ -72,6 +76,7 @@ func (*UtilsStruct) ExecuteCreateCollection(flagSet *pflag.FlagSet) { Tolerance: tolerance, } + log.Debugf("Calling CreateCollection() with argument collectionInput: %+v", collectionInput) txn, err := cmdUtils.CreateCollection(client, config, collectionInput) utils.CheckError("CreateCollection error: ", err) err = razorUtils.WaitForBlockCompletion(client, txn.String()) @@ -81,6 +86,7 @@ func (*UtilsStruct) ExecuteCreateCollection(flagSet *pflag.FlagSet) { //This function allows the admin to create collction if existing jobs are present func (*UtilsStruct) CreateCollection(client *ethclient.Client, config types.Configurations, collectionInput types.CreateCollectionInput) (common.Hash, error) { jobIds := razorUtils.ConvertUintArrayToUint16Array(collectionInput.JobIds) + log.Debug("CreateCollection: Uint16 jobIds: ", jobIds) _, err := cmdUtils.WaitForAppropriateState(client, "create collection", 4) if err != nil { log.Error("Error in fetching state") @@ -97,6 +103,7 @@ func (*UtilsStruct) CreateCollection(client *ethclient.Client, config types.Conf Parameters: []interface{}{collectionInput.Tolerance, collectionInput.Power, collectionInput.Aggregation, jobIds, collectionInput.Name}, ABI: bindings.CollectionManagerABI, }) + log.Debugf("Executing CreateCollection transaction with tolerance: %d, power = %d , aggregation = %d, jobIds = %v, name = %s", collectionInput.Tolerance, collectionInput.Power, collectionInput.Aggregation, jobIds, collectionInput.Name) txn, err := assetManagerUtils.CreateCollection(client, txnOpts, collectionInput.Tolerance, collectionInput.Power, collectionInput.Aggregation, jobIds, collectionInput.Name) if err != nil { log.Error("Error in creating collection") @@ -115,6 +122,7 @@ func init() { Account string JobIds []uint AggregationMethod uint32 + Password string Power int8 Tolerance uint32 ) @@ -125,6 +133,7 @@ func init() { createCollectionCmd.Flags().Uint32VarP(&AggregationMethod, "aggregation", "", 1, "aggregation method to be used") createCollectionCmd.Flags().Uint32VarP(&Tolerance, "tolerance", "", 0, "tolerance") createCollectionCmd.Flags().Int8VarP(&Power, "power", "", 0, "multiplier for the collection") + createCollectionCmd.Flags().StringVarP(&Password, "password", "", "", "password path of job creator to protect the keystore") nameErr := createCollectionCmd.MarkFlagRequired("name") utils.CheckError("Name error: ", nameErr) diff --git a/cmd/createCollection_test.go b/cmd/createCollection_test.go index 4e3ab38b..27206fbb 100644 --- a/cmd/createCollection_test.go +++ b/cmd/createCollection_test.go @@ -302,7 +302,7 @@ func TestExecuteCreateCollection(t *testing.T) { utilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet")) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) - utilsMock.On("AssignPassword").Return(tt.args.password) + utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) flagsetUtilsMock.On("GetStringAddress", flagSet).Return(tt.args.address, tt.args.addressErr) flagsetUtilsMock.On("GetStringName", flagSet).Return(tt.args.name, tt.args.nameErr) flagsetUtilsMock.On("GetUintSliceJobIds", flagSet).Return(tt.args.jobId, tt.args.jobIdErr) diff --git a/cmd/createJob.go b/cmd/createJob.go index bbbde9c2..68bbd1b7 100644 --- a/cmd/createJob.go +++ b/cmd/createJob.go @@ -2,15 +2,16 @@ package cmd import ( - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/spf13/pflag" "razor/core" "razor/core/types" "razor/logger" "razor/pkg/bindings" "razor/utils" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/spf13/pflag" + "github.com/spf13/cobra" ) @@ -37,6 +38,7 @@ func initialiseCreateJob(cmd *cobra.Command, args []string) { func (*UtilsStruct) ExecuteCreateJob(flagSet *pflag.FlagSet) { config, err := cmdUtils.GetConfigData() utils.CheckError("Error in getting config: ", err) + log.Debugf("ExecuteCreateJob: Config: %+v", config) client := razorUtils.ConnectToClient(config.Provider) @@ -44,9 +46,11 @@ func (*UtilsStruct) ExecuteCreateJob(flagSet *pflag.FlagSet) { utils.CheckError("Error in getting address: ", err) logger.SetLoggerParameters(client, address) + log.Debug("Checking to assign log file...") razorUtils.AssignLogFile(flagSet) - password := razorUtils.AssignPassword() + log.Debug("Getting password...") + password := razorUtils.AssignPassword(flagSet) name, err := flagSetUtils.GetStringName(flagSet) utils.CheckError("Error in getting name: ", err) @@ -76,7 +80,7 @@ func (*UtilsStruct) ExecuteCreateJob(flagSet *pflag.FlagSet) { Weight: weight, Power: power, } - + log.Debugf("ExecuteCreateJob: Calling CreateJob() with argument jobInput: %+v", jobInput) txn, err := cmdUtils.CreateJob(client, config, jobInput) utils.CheckError("CreateJob error: ", err) err = razorUtils.WaitForBlockCompletion(client, txn.String()) @@ -99,6 +103,7 @@ func (*UtilsStruct) CreateJob(client *ethclient.Client, config types.Configurati txnOpts := razorUtils.GetTxnOpts(txnArgs) log.Info("Creating Job...") + log.Debugf("CreateJob: Executing CreateJob transaction with weight = %d, power = %d, selector type = %d, name = %s, selector = %s, URl = %s", jobInput.Weight, jobInput.Power, jobInput.SelectorType, jobInput.Name, jobInput.Selector, jobInput.Url) txn, err := assetManagerUtils.CreateJob(txnArgs.Client, txnOpts, jobInput.Weight, jobInput.Power, jobInput.SelectorType, jobInput.Name, jobInput.Selector, jobInput.Url) if err != nil { return core.NilHash, err @@ -117,6 +122,7 @@ func init() { Name string Power int8 Account string + Password string Weight uint8 ) @@ -127,6 +133,7 @@ func init() { createJobCmd.Flags().Int8VarP(&Power, "power", "", 0, "power") createJobCmd.Flags().Uint8VarP(&Weight, "weight", "", 0, "weight assigned to the job") createJobCmd.Flags().StringVarP(&Account, "address", "a", "", "address of the job creator") + createJobCmd.Flags().StringVarP(&Password, "password", "", "", "password path of job creator to protect the keystore") urlErr := createJobCmd.MarkFlagRequired("url") utils.CheckError("URL error: ", urlErr) diff --git a/cmd/createJob_test.go b/cmd/createJob_test.go index 5bb77b54..14baa81f 100644 --- a/cmd/createJob_test.go +++ b/cmd/createJob_test.go @@ -320,7 +320,7 @@ func TestExecuteCreateJob(t *testing.T) { utilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet")) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) - utilsMock.On("AssignPassword").Return(tt.args.password) + utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) flagsetUtilsMock.On("GetStringAddress", flagSet).Return(tt.args.address, tt.args.addressErr) flagsetUtilsMock.On("GetStringName", flagSet).Return(tt.args.name, tt.args.nameErr) flagsetUtilsMock.On("GetStringUrl", flagSet).Return(tt.args.url, tt.args.urlErr) diff --git a/cmd/create_test.go b/cmd/create_test.go index 0c8d40d7..0df1acd2 100644 --- a/cmd/create_test.go +++ b/cmd/create_test.go @@ -144,7 +144,7 @@ func TestExecuteCreate(t *testing.T) { cmdUtils = cmdUtilsMock utilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet")) - utilsMock.On("AssignPassword").Return(tt.args.password) + utilsMock.On("AssignPassword", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.password) cmdUtilsMock.On("Create", mock.AnythingOfType("string")).Return(tt.args.account, tt.args.accountErr) utils := &UtilsStruct{} diff --git a/cmd/delegate.go b/cmd/delegate.go index 9bb2a75c..1e2f376f 100644 --- a/cmd/delegate.go +++ b/cmd/delegate.go @@ -34,28 +34,36 @@ func initialiseDelegate(cmd *cobra.Command, args []string) { func (*UtilsStruct) ExecuteDelegate(flagSet *pflag.FlagSet) { config, err := cmdUtils.GetConfigData() utils.CheckError("Error in getting config: ", err) + log.Debugf("ExecuteDelegate: Config: %+v", config) client := razorUtils.ConnectToClient(config.Provider) address, err := flagSetUtils.GetStringAddress(flagSet) utils.CheckError("Error in getting address: ", err) + log.Debug("ExecuteDelegate: Address: ", address) logger.SetLoggerParameters(client, address) + log.Debug("Checking to assign log file...") razorUtils.AssignLogFile(flagSet) - password := razorUtils.AssignPassword() + log.Debug("Getting password...") + password := razorUtils.AssignPassword(flagSet) stakerId, err := flagSetUtils.GetUint32StakerId(flagSet) utils.CheckError("Error in getting stakerId: ", err) - + log.Debug("ExecuteDelegate: Staker Id: ", stakerId) balance, err := razorUtils.FetchBalance(client, address) utils.CheckError("Error in fetching razor balance for account "+address+": ", err) + log.Debug("ExecuteDelegate: Balance: ", balance) + log.Debug("Getting amount in wei...") valueInWei, err := cmdUtils.AssignAmountInWei(flagSet) utils.CheckError("Error in getting amount: ", err) + log.Debug("Checking for sufficient balance...") razorUtils.CheckAmountAndBalance(valueInWei, balance) + log.Debug("Checking whether sFuel balance is not 0...") razorUtils.CheckEthBalanceIsZero(client, address) txnArgs := types.TransactionOptions{ @@ -67,6 +75,7 @@ func (*UtilsStruct) ExecuteDelegate(flagSet *pflag.FlagSet) { Config: config, } + log.Debugf("ExecuteDelegate: Calling Approve() with transaction arguments: %+v", txnArgs) approveTxnHash, err := cmdUtils.Approve(txnArgs) utils.CheckError("Approve error: ", err) @@ -75,6 +84,7 @@ func (*UtilsStruct) ExecuteDelegate(flagSet *pflag.FlagSet) { utils.CheckError("Error in WaitForBlockCompletion for approve: ", err) } + log.Debug("ExecuteDelegate:Calling Delegate() with stakerId: ", stakerId) delegateTxnHash, err := cmdUtils.Delegate(txnArgs, stakerId) utils.CheckError("Delegate error: ", err) err = razorUtils.WaitForBlockCompletion(client, delegateTxnHash.String()) @@ -90,6 +100,7 @@ func (*UtilsStruct) Delegate(txnArgs types.TransactionOptions, stakerId uint32) txnArgs.Parameters = []interface{}{stakerId, txnArgs.Amount} delegationTxnOpts := razorUtils.GetTxnOpts(txnArgs) log.Info("Sending Delegate transaction...") + log.Debugf("Executing Delegate transaction with stakerId = %d, amount = %s", stakerId, txnArgs.Amount) txn, err := stakeManagerUtils.Delegate(txnArgs.Client, delegationTxnOpts, stakerId, txnArgs.Amount) if err != nil { return common.Hash{0x00}, err @@ -104,12 +115,14 @@ func init() { Amount string Address string StakerId uint32 + Password string WeiRazor bool ) delegateCmd.Flags().StringVarP(&Amount, "value", "v", "0", "amount to stake (in Wei)") delegateCmd.Flags().StringVarP(&Address, "address", "a", "", "your account address") delegateCmd.Flags().Uint32VarP(&StakerId, "stakerId", "", 0, "staker id") + delegateCmd.Flags().StringVarP(&Password, "password", "", "", "password path to protect the keystore") delegateCmd.Flags().BoolVarP(&WeiRazor, "weiRazor", "", false, "value can be passed in wei") valueErr := delegateCmd.MarkFlagRequired("value") diff --git a/cmd/delegate_test.go b/cmd/delegate_test.go index db2b43ef..8973b06a 100644 --- a/cmd/delegate_test.go +++ b/cmd/delegate_test.go @@ -265,7 +265,7 @@ func TestExecuteDelegate(t *testing.T) { utilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet")) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) - utilsMock.On("AssignPassword").Return(tt.args.password) + utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) flagSetUtilsMock.On("GetStringAddress", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.address, tt.args.addressErr) flagSetUtilsMock.On("GetUint32StakerId", flagSet).Return(tt.args.stakerId, tt.args.stakerIdErr) utilsMock.On("ConnectToClient", mock.AnythingOfType("string")).Return(client) diff --git a/cmd/dispute.go b/cmd/dispute.go index 1b96dd26..f11b55f0 100644 --- a/cmd/dispute.go +++ b/cmd/dispute.go @@ -6,7 +6,7 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - types2 "github.com/ethereum/go-ethereum/core/types" + Types "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" solsha3 "github.com/miguelmota/go-solidity-sha3" "math/big" @@ -21,34 +21,40 @@ import ( var ( giveSortedLeafIds []int - disputedFlag bool ) //blockId is id of the block //This function handles the dispute and if there is any error it returns the error -func (*UtilsStruct) HandleDispute(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, blockNumber *big.Int, rogueData types.Rogue) error { - disputedFlag = false +func (*UtilsStruct) HandleDispute(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, blockNumber *big.Int, rogueData types.Rogue, backupNodeActionsToIgnore []string) error { sortedProposedBlockIds, err := razorUtils.GetSortedProposedBlockIds(client, epoch) if err != nil { log.Error("Error in fetching sorted proposed block id: ", err) return err } - log.Debug("SortedProposedBlockIds: ", sortedProposedBlockIds) + log.Debug("HandleDispute: SortedProposedBlockIds: ", sortedProposedBlockIds) biggestStake, biggestStakerId, err := cmdUtils.GetBiggestStakeAndId(client, account.Address, epoch) if err != nil { return err } - log.Debug("Biggest Stake: ", biggestStake) + log.Debugf("HandleDispute: Biggest stake: %s, Biggest staker Id: %d", biggestStake, biggestStakerId) - medians, revealedCollectionIds, revealedDataMaps, err := cmdUtils.GetLocalMediansData(client, account, epoch, blockNumber, rogueData) + log.Debugf("HandleDispute: Calling GetLocalMediansData() with arguments epoch = %d, blockNumber = %d, rogueData = %+v", epoch, blockNumber, rogueData) + locallyCalculatedData, err := cmdUtils.GetLocalMediansData(client, account, epoch, blockNumber, rogueData) if err != nil { return err } + medians := locallyCalculatedData.MediansData + revealedCollectionIds := locallyCalculatedData.RevealedCollectionIds + revealedDataMaps := locallyCalculatedData.RevealedDataMaps - randomSortedProposedBlockIds := utils.UtilsInterface.Shuffle(sortedProposedBlockIds) //shuffles the sortedProposedBlockIds array + log.Debug("HandleDispute: Local Medians data:", medians) + log.Debug("HandleDispute: Revealed collection ids:", revealedCollectionIds) + log.Debug("HandleDispute: Local revealed data maps:", revealedDataMaps) + + randomSortedProposedBlockIds := utils.Shuffle(sortedProposedBlockIds) //shuffles the sortedProposedBlockIds array transactionOptions := types.TransactionOptions{ Client: client, Password: account.Password, @@ -56,22 +62,25 @@ func (*UtilsStruct) HandleDispute(client *ethclient.Client, config types.Configu ChainId: core.ChainId, Config: config, } + log.Debug("HandleDispute: Shuffled sorted proposed blocks: ", randomSortedProposedBlockIds) + log.Debug("Iterating over random sorted proposed blocks to check dispute...") for _, blockId := range randomSortedProposedBlockIds { - proposedBlock, err := razorUtils.GetProposedBlock(client, epoch, uint32(blockId)) + proposedBlock, err := razorUtils.GetProposedBlock(client, epoch, blockId) if err != nil { log.Error(err) continue } - log.Debug("Proposed block ", blockId, proposedBlock) + log.Debug("HandleDispute: Block ID: ", blockId) + log.Debug("HandleDispute: Proposed block ", proposedBlock) //blockIndex is index of blockId in sortedProposedBlock - blockIndex := utils.IndexOf(sortedProposedBlockIds, uint32(blockId)) + blockIndex := utils.IndexOf(sortedProposedBlockIds, blockId) if blockIndex == -1 { log.Error("Block is not present in SortedProposedBlockIds array") continue } - + log.Debug("HandleDispute: Block Index: ", blockIndex) // Biggest staker dispute if proposedBlock.BiggestStake.Cmp(biggestStake) != 0 && proposedBlock.Valid { log.Debug("Biggest Stake in proposed block: ", proposedBlock.BiggestStake) @@ -84,6 +93,7 @@ func (*UtilsStruct) HandleDispute(client *ethclient.Client, config types.Configu ChainId: core.ChainId, Config: config, }) + log.Debugf("Executing DisputeBiggestStakeProposed transaction with arguments epoch = %d, blockIndex = %d, biggest staker Id = %d", epoch, blockIndex, biggestStakerId) disputeBiggestStakeProposedTxn, err := blockManagerUtils.DisputeBiggestStakeProposed(client, txnOpts, epoch, uint8(blockIndex), biggestStakerId) if err != nil { log.Error(err) @@ -94,7 +104,7 @@ func (*UtilsStruct) HandleDispute(client *ethclient.Client, config types.Configu //If dispute happens, then storing the bountyId into disputeData file if WaitForBlockCompletionErr == nil { - disputedFlag = true + log.Debug("Storing bounty Id in dispute data file....") err = cmdUtils.StoreBountyId(client, account) if err != nil { log.Error(err) @@ -105,9 +115,10 @@ func (*UtilsStruct) HandleDispute(client *ethclient.Client, config types.Configu } // Ids Dispute - log.Debug("Locally revealed collection ids: ", revealedCollectionIds) - log.Debug("Revealed collection ids in the block ", proposedBlock.Ids) + log.Debug("HandleDispute: Locally revealed collection ids: ", revealedCollectionIds) + log.Debug("HandleDispute: Revealed collection ids in the block ", proposedBlock.Ids) + log.Debugf("HandleDispute: Calling CheckDisputeForIds() with arguments epoch = %d, blockIndex = %d, proposed revealed Ids = %v, locally calculated revealed Ids = %v", epoch, blockIndex, proposedBlock.Ids, revealedCollectionIds) idDisputeTxn, err := cmdUtils.CheckDisputeForIds(client, transactionOptions, epoch, uint8(blockIndex), proposedBlock.Ids, revealedCollectionIds) if err != nil { log.Error("Error in disputing: ", err) @@ -118,7 +129,7 @@ func (*UtilsStruct) HandleDispute(client *ethclient.Client, config types.Configu //If dispute happens, then storing the bountyId into disputeData file if WaitForBlockCompletionErr == nil { - disputedFlag = true + log.Debug("Storing bounty Id in dispute data file...") err = cmdUtils.StoreBountyId(client, account) if err != nil { log.Error(err) @@ -130,26 +141,31 @@ func (*UtilsStruct) HandleDispute(client *ethclient.Client, config types.Configu // Median Value dispute isEqual, mismatchIndex := utils.IsEqual(proposedBlock.Medians, medians) - if !isEqual { + if !isEqual && !utils.Contains(backupNodeActionsToIgnore, "disputeMedians") { log.Warn("BLOCK NOT MATCHING WITH LOCAL CALCULATIONS.") - log.Debug("Block Values: ", proposedBlock.Medians) - log.Debug("Local Calculations: ", medians) + log.Debug("HandleDispute: Block Values: ", proposedBlock.Medians) + log.Debug("HandleDispute: Local Calculations: ", medians) if proposedBlock.Valid && len(proposedBlock.Ids) != 0 && len(proposedBlock.Medians) != 0 { // median locally calculated: [100, 200, 300, 500] median proposed: [100, 230, 300, 500] // ids [1, 2, 3, 4] // Sorted revealed values would be the vote values for the wrong median, here 230 + log.Debug("HandleDispute: Mismatch index while iterating: ", mismatchIndex) collectionIdOfWrongMedian := proposedBlock.Ids[mismatchIndex] + log.Debug("HandleDispute: Collection Id of wrong median: ", collectionIdOfWrongMedian) //collectionId starts from 1 and in SortedRevealedValues, the keys start from 0 which are collectionId-1 mapping to respective revealed data for that collectionId. //e.g. collectionId = [1,2,3,4] & Sorted Reveal Votes: map[0:[100] 1:[200 202] 2:[300]] //Here 0th key in map represents collectionId 1. sortedValues := revealedDataMaps.SortedRevealedValues[collectionIdOfWrongMedian-1] + log.Debug("HandleDispute: Sorted values: ", sortedValues) leafId, err := utils.UtilsInterface.GetLeafIdOfACollection(client, collectionIdOfWrongMedian) if err != nil { log.Error("Error in leaf id: ", err) continue } + log.Debug("HandleDispute: Leaf Id: ", leafId) + log.Debugf("Calling Dispute() with arguments epoch = %d, blockIndex = %d, proposed block = %+v, leafId = %d, sortedValues = %s", epoch, uint8(blockIndex), proposedBlock, leafId, sortedValues) disputeErr := cmdUtils.Dispute(client, config, account, epoch, uint8(blockIndex), proposedBlock, leafId, sortedValues) if disputeErr != nil { log.Error("Error in disputing...", disputeErr) @@ -165,84 +181,85 @@ func (*UtilsStruct) HandleDispute(client *ethclient.Client, config types.Configu } } - blockManager := razorUtils.GetBlockManager(client) - txnOpts := razorUtils.GetTxnOpts(types.TransactionOptions{ - Client: client, - Password: account.Password, - AccountAddress: account.Address, - ChainId: core.ChainId, - Config: config, - }) - if disputedFlag { - cmdUtils.ResetDispute(client, blockManager, txnOpts, epoch) - } - giveSortedLeafIds = []int{} return nil } //This function returns the local median data -func (*UtilsStruct) GetLocalMediansData(client *ethclient.Client, account types.Account, epoch uint32, blockNumber *big.Int, rogueData types.Rogue) ([]*big.Int, []uint16, *types.RevealedDataMaps, error) { - - if _mediansData == nil && !rogueData.IsRogue { +func (*UtilsStruct) GetLocalMediansData(client *ethclient.Client, account types.Account, epoch uint32, blockNumber *big.Int, rogueData types.Rogue) (types.ProposeFileData, error) { + if (globalProposedDataStruct.MediansData == nil && !rogueData.IsRogue) || epoch != globalProposedDataStruct.Epoch { + log.Debug("Global propose data struct is not updated, getting the proposed data from file...") fileName, err := razorUtils.GetProposeDataFileName(account.Address) if err != nil { log.Error("Error in getting file name to read median data: ", err) goto CalculateMedian } - proposedata, err := razorUtils.ReadFromProposeJsonFile(fileName) + log.Debug("GetLocalMediansData: Propose data file path: ", fileName) + proposedData, err := razorUtils.ReadFromProposeJsonFile(fileName) if err != nil { - log.Errorf("Error in getting propose data from file %s: %t", fileName, err) + log.Errorf("Error in getting propose data from file %s: %v", fileName, err) goto CalculateMedian } - if proposedata.Epoch != epoch { - log.Errorf("File %s doesn't contain latest median data: %t", fileName, err) + log.Debugf("GetLocalMediansData: Proposed data from file: %+v", proposedData) + if proposedData.Epoch != epoch { + log.Errorf("File %s doesn't contain latest median data", fileName) goto CalculateMedian } - _mediansData = proposedata.MediansData - _revealedDataMaps = proposedata.RevealedDataMaps - _revealedCollectionIds = proposedata.RevealedCollectionIds + log.Debug("Updating global proposed data struct...") + updateGlobalProposedDataStruct(proposedData) + log.Debugf("GetLocalMediansData: Global proposed data struct: %+v", globalProposedDataStruct) } CalculateMedian: stakerId, err := razorUtils.GetStakerId(client, account.Address) if err != nil { log.Error("Error in getting stakerId: ", err) - return nil, nil, nil, err + return types.ProposeFileData{}, err } - lastProposedEpoch, err := cmdUtils.GetLastProposedEpoch(client, blockNumber, stakerId) + log.Debug("GetLocalMediansData: Staker Id: ", stakerId) + lastProposedEpoch, err := razorUtils.GetEpochLastProposed(client, stakerId) if err != nil { log.Error("Error in getting last proposed epoch: ", err) - return nil, nil, nil, err + return types.ProposeFileData{}, err } + log.Debug("GetLocalMediansData: Last proposed epoch: ", lastProposedEpoch) - nilProposedData := _mediansData == nil || _revealedCollectionIds == nil || _revealedDataMaps == nil + nilProposedData := globalProposedDataStruct.MediansData == nil || globalProposedDataStruct.RevealedDataMaps == nil || globalProposedDataStruct.RevealedCollectionIds == nil epochCheck := epoch != lastProposedEpoch if nilProposedData || rogueData.IsRogue || epochCheck { + log.Debug("Calculating the medians data again...") + log.Debugf("GetLocalMediansData: Calling MakeBlock() with arguments blockNumber = %s, epoch = %d, rogueData = %+v", blockNumber, epoch, types.Rogue{IsRogue: false}) medians, revealedCollectionIds, revealedDataMaps, err := cmdUtils.MakeBlock(client, blockNumber, epoch, types.Rogue{IsRogue: false}) if err != nil { log.Error("Error in calculating block medians") - return nil, nil, nil, err + return types.ProposeFileData{}, err } - _mediansData = medians - _revealedCollectionIds = revealedCollectionIds - _revealedDataMaps = revealedDataMaps - } - - log.Debug("Locally calculated data:") - log.Debugf("Medians: %d", _mediansData) - return _mediansData, _revealedCollectionIds, _revealedDataMaps, nil + log.Debug("Updating global proposed data struct...") + updateGlobalProposedDataStruct(types.ProposeFileData{ + MediansData: medians, + RevealedCollectionIds: revealedCollectionIds, + RevealedDataMaps: revealedDataMaps, + Epoch: epoch, + }) + log.Debugf("GetLocalMediansData: Global proposed data struct: %+v", globalProposedDataStruct) + } + + log.Debugf("Locally calculated data, Medians: %s", globalProposedDataStruct.MediansData) + return globalProposedDataStruct, nil } //This function check for the dispute in different type of Id's -func (*UtilsStruct) CheckDisputeForIds(client *ethclient.Client, transactionOpts types.TransactionOptions, epoch uint32, blockIndex uint8, idsInProposedBlock []uint16, revealedCollectionIds []uint16) (*types2.Transaction, error) { +func (*UtilsStruct) CheckDisputeForIds(client *ethclient.Client, transactionOpts types.TransactionOptions, epoch uint32, blockIndex uint8, idsInProposedBlock []uint16, revealedCollectionIds []uint16) (*Types.Transaction, error) { //checking for hashing whether there is any dispute or not hashIdsInProposedBlock := solsha3.SoliditySHA3([]string{"uint16[]"}, []interface{}{idsInProposedBlock}) + log.Debug("CheckDisputeForIds: Hash of reveal Ids in proposed block: ", hashIdsInProposedBlock) hashRevealedCollectionIds := solsha3.SoliditySHA3([]string{"uint16[]"}, []interface{}{revealedCollectionIds}) + log.Debug("CheckDisputeForIds: Hash of locally calculated reveal collection Ids: ", hashRevealedCollectionIds) isEqual, _ := utils.IsEqualByte(hashIdsInProposedBlock, hashRevealedCollectionIds) if isEqual { + log.Debug("Revealed collection Ids are correct, no need to dispute for ids") return nil, nil } @@ -254,7 +271,7 @@ func (*UtilsStruct) CheckDisputeForIds(client *ethclient.Client, transactionOpts transactionOpts.Parameters = []interface{}{epoch, blockIndex, index0, index1} txnOpts := razorUtils.GetTxnOpts(transactionOpts) log.Debug("Disputing sorted order of ids!") - log.Debugf("Epoch: %d, blockIndex: %d, index0: %d, index1: %d", epoch, blockIndex, index0, index1) + log.Debugf("CheckDisputeForIds: Executing DisputeOnOrderOfIds transaction with arguments epoch: %d, blockIndex: %d, index0: %d, index1: %d", epoch, blockIndex, index0, index1) return blockManagerUtils.DisputeOnOrderOfIds(client, txnOpts, epoch, blockIndex, big.NewInt(int64(index0)), big.NewInt(int64(index1))) } @@ -272,7 +289,7 @@ func (*UtilsStruct) CheckDisputeForIds(client *ethclient.Client, transactionOpts } txnOpts.GasLimit = incrementedGasLimit log.Debug("Disputing collection id should be present!") - log.Debugf("Epoch: %d, blockIndex: %d, missingCollectionId: %d", epoch, blockIndex, missingCollectionId) + log.Debugf("CheckDisputeForIds: Executing DisputeCollectionIdShouldBePresent transaction with arguments epoch: %d, blockIndex: %d, missingCollectionId: %d", epoch, blockIndex, missingCollectionId) return blockManagerUtils.DisputeCollectionIdShouldBePresent(client, txnOpts, epoch, blockIndex, missingCollectionId) } @@ -290,7 +307,7 @@ func (*UtilsStruct) CheckDisputeForIds(client *ethclient.Client, transactionOpts } txnOpts.GasLimit = incrementedGasLimit log.Debug("Disputing collection id should be absent!") - log.Debugf("Epoch: %d, blockIndex: %d, presentCollectionId: %d, positionOfPresentValue: %d", epoch, blockIndex, presentCollectionId, positionOfPresentValue) + log.Debugf("CheckDisputeForIds: Executing DisputeCollectionIdShouldBeAbsent transaction with arguments epoch: %d, blockIndex: %d, presentCollectionId: %d, positionOfPresentValue: %d", epoch, blockIndex, presentCollectionId, positionOfPresentValue) return blockManagerUtils.DisputeCollectionIdShouldBeAbsent(client, txnOpts, epoch, blockIndex, presentCollectionId, big.NewInt(int64(positionOfPresentValue))) } @@ -301,68 +318,143 @@ func (*UtilsStruct) CheckDisputeForIds(client *ethclient.Client, transactionOpts func (*UtilsStruct) Dispute(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, blockIndex uint8, proposedBlock bindings.StructsBlock, leafId uint16, sortedValues []*big.Int) error { blockManager := razorUtils.GetBlockManager(client) - txnOpts := razorUtils.GetTxnOpts(types.TransactionOptions{ + txnArgs := types.TransactionOptions{ Client: client, Password: account.Password, AccountAddress: account.Address, ChainId: core.ChainId, Config: config, - }) + } if !utils.Contains(giveSortedLeafIds, leafId) { - cmdUtils.GiveSorted(client, blockManager, txnOpts, epoch, leafId, sortedValues) + var ( + start int + end int + ) + lenOfSortedValues := len(sortedValues) + for { + if start >= end && start != 0 && end != 0 { + break + } + if end == 0 { + end = lenOfSortedValues + } + log.Debugf("Dispute: Calling GiveSorted with arguments epoch = %d, leafId = %d, sortedValues = %s", epoch, leafId, sortedValues[start:end]) + err := cmdUtils.GiveSorted(client, blockManager, txnArgs, epoch, leafId, sortedValues[start:end]) + if err != nil { + if err.Error() == errors.New("gas limit reached").Error() { + end = end / 2 + } else { + log.Error("Error in GiveSorted: ", err) + txnOpts := razorUtils.GetTxnOpts(txnArgs) + log.Debugf("Dispute: Calling CheckToDoResetDispute with arguments epoch = %d, sortedValues = %s", epoch, sortedValues) + cmdUtils.CheckToDoResetDispute(client, blockManager, txnOpts, epoch, sortedValues) + return err + } + } else { + threshold := end - start + start = end + if end != lenOfSortedValues { + end = end + threshold + if end > lenOfSortedValues { + end = lenOfSortedValues + } + } + } + } + // Adding leafId to giveSortedLeafIds as giveSorted is done for that leafId + giveSortedLeafIds = append(giveSortedLeafIds, int(leafId)) } + log.Debugf("Dispute: Calling GetCollectionIdPositionInBlock with arguments leafId = %d, proposed block = %+v", leafId, proposedBlock) + positionOfCollectionInBlock := cmdUtils.GetCollectionIdPositionInBlock(client, leafId, proposedBlock) + log.Debug("Dispute: Position of collection id in block: ", positionOfCollectionInBlock) log.Info("Finalizing dispute...") - finalizeDisputeTxnOpts := razorUtils.GetTxnOpts(types.TransactionOptions{ - Client: client, - Password: account.Password, - AccountAddress: account.Address, - ChainId: core.ChainId, - Config: config, - }) - positionOfCollectionInBlock := cmdUtils.GetCollectionIdPositionInBlock(client, leafId, proposedBlock) + finalizeDisputeTxnArgs := txnArgs + finalizeDisputeTxnArgs.ContractAddress = core.BlockManagerAddress + finalizeDisputeTxnArgs.MethodName = "finalizeDispute" + finalizeDisputeTxnArgs.ABI = bindings.BlockManagerABI + finalizeDisputeTxnArgs.Parameters = []interface{}{epoch, blockIndex, positionOfCollectionInBlock} + finalizeDisputeTxnOpts := razorUtils.GetTxnOpts(finalizeDisputeTxnArgs) + + log.Debugf("Executing FinalizeDispute transaction with arguments epoch = %d, blockIndex = %d, positionOfCollectionInBlock = %d", epoch, blockIndex, positionOfCollectionInBlock) finalizeTxn, err := blockManagerUtils.FinalizeDispute(client, finalizeDisputeTxnOpts, epoch, blockIndex, positionOfCollectionInBlock) if err != nil { - return err + log.Error("Error in FinalizeDispute: ", err) } - log.Info("Txn Hash: ", transactionUtils.Hash(finalizeTxn)) - WaitForBlockCompletionErr := razorUtils.WaitForBlockCompletion(client, transactionUtils.Hash(finalizeTxn).String()) - //If dispute happens, then storing the bountyId into disputeData file - if WaitForBlockCompletionErr == nil { - disputedFlag = true - err = cmdUtils.StoreBountyId(client, account) - if err != nil { - return err + var nilTransaction *Types.Transaction + + if finalizeTxn != nilTransaction { + log.Debug("Dispute: Checking mining status of FinalizeDispute transaction...") + WaitForBlockCompletionErr := razorUtils.WaitForBlockCompletion(client, transactionUtils.Hash(finalizeTxn).String()) + //If dispute happens, then storing the bountyId into disputeData file + if WaitForBlockCompletionErr == nil { + log.Debug("Storing bounty Id in dispute data file...") + err = cmdUtils.StoreBountyId(client, account) + if err != nil { + return err + } + } else { + log.Error("Error in WaitForBlockCompletion for FinalizeDispute: ", WaitForBlockCompletionErr) } } + + //Resetting dispute irrespective of FinalizeDispute transaction status + log.Debug("Resetting dispute ...") + + resetDisputeTxnArgs := txnArgs + resetDisputeTxnArgs.ContractAddress = core.BlockManagerAddress + resetDisputeTxnArgs.MethodName = "resetDispute" + resetDisputeTxnArgs.ABI = bindings.BlockManagerABI + resetDisputeTxnArgs.Parameters = []interface{}{epoch} + resetDisputeTxnOpts := razorUtils.GetTxnOpts(resetDisputeTxnArgs) + + cmdUtils.ResetDispute(client, blockManager, resetDisputeTxnOpts, epoch) + return nil } //This function sorts the Id's recursively -func GiveSorted(client *ethclient.Client, blockManager *bindings.BlockManager, txnOpts *bind.TransactOpts, epoch uint32, leafId uint16, sortedValues []*big.Int) { +func GiveSorted(client *ethclient.Client, blockManager *bindings.BlockManager, txnArgs types.TransactionOptions, epoch uint32, leafId uint16, sortedValues []*big.Int) error { if len(sortedValues) == 0 { - return + return errors.New("length of sortedValues is 0") } + callOpts := razorUtils.GetOptions() + txnOpts := razorUtils.GetTxnOpts(txnArgs) + disputesMapping, err := blockManagerUtils.Disputes(client, &callOpts, epoch, common.HexToAddress(txnArgs.AccountAddress)) + if err != nil { + log.Error("Error in getting disputes mapping: ", disputesMapping) + return err + } + log.Debugf("GiveSorted: Disputes mapping: %+v", disputesMapping) + + if disputesMapping.LastVisitedValue.Cmp(sortedValues[len(sortedValues)-1]) == 0 { + return errors.New("giveSorted already done") + } + + isGiveSortedInitiated := disputesMapping.LastVisitedValue.Cmp(big.NewInt(0)) > 0 && disputesMapping.AccWeight.Cmp(big.NewInt(0)) > 0 + if isGiveSortedInitiated && disputesMapping.LeafId != leafId { + log.Error("Give sorted is in progress for another leafId") + return errors.New("another giveSorted in progress") + } + log.Debug("GiveSorted: Is give sorted initiated: ", isGiveSortedInitiated) + + log.Debugf("Executing GiveSorted transaction with arguments epoch = %d, leafId = %d , sortedValues = %s", epoch, leafId, sortedValues) txn, err := blockManagerUtils.GiveSorted(blockManager, txnOpts, epoch, leafId, sortedValues) if err != nil { - if err.Error() == errors.New("gas limit reached").Error() { - log.Error("Error in calling GiveSorted: ", err) - mid := len(sortedValues) / 2 - GiveSorted(client, blockManager, txnOpts, epoch, leafId, sortedValues[:mid]) - GiveSorted(client, blockManager, txnOpts, epoch, leafId, sortedValues[mid:]) - } else { - return - } + return err } + log.Info("Calling GiveSorted...") log.Info("Txn Hash: ", transactionUtils.Hash(txn)) giveSortedLeafIds = append(giveSortedLeafIds, int(leafId)) err = razorUtils.WaitForBlockCompletion(client, transactionUtils.Hash(txn).String()) if err != nil { log.Error("Error in WaitForBlockCompletion for giveSorted: ", err) + return err } + return nil } //This function returns the collection Id position in block @@ -373,8 +465,10 @@ func (*UtilsStruct) GetCollectionIdPositionInBlock(client *ethclient.Client, lea log.Error("Error in fetching collection id from leaf id") return nil } + log.Debug("GetCollectionIdPositionInBlock: Id to be disputed: ", idToBeDisputed) for i := 0; i < len(ids); i++ { if ids[i] == idToBeDisputed { + log.Debug("GetCollectionIdPositionInBlock: Position of collectionId in block: ", i) return big.NewInt(int64(i)) } } @@ -387,6 +481,7 @@ func (*UtilsStruct) StoreBountyId(client *ethclient.Client, account types.Accoun if err != nil { return err } + log.Debug("StoreBountyId: Dispute data file path: ", disputeFilePath) var latestBountyId uint32 @@ -395,17 +490,21 @@ func (*UtilsStruct) StoreBountyId(client *ethclient.Client, account types.Accoun log.Error("Error in fetching block: ", err) return err } + log.Debug("StoreBountyId: Latest header: ", latestHeader) + log.Debugf("StoreBountyId: Calling GetBountyIdFromEvents with arguments blockNumber = %d, address = %s", latestHeader.Number, account.Address) latestBountyId, err = cmdUtils.GetBountyIdFromEvents(client, latestHeader.Number, account.Address) if err != nil { return err } if _, err := path.OSUtilsInterface.Stat(disputeFilePath); !errors.Is(err, os.ErrNotExist) { + log.Debug("Fetching dispute data from dispute data file...") disputeData, err = razorUtils.ReadFromDisputeJsonFile(disputeFilePath) if err != nil { return err } + log.Debugf("StoreBountyId: Dispute data: %+v", disputeData) } if latestBountyId != 0 { @@ -414,6 +513,7 @@ func (*UtilsStruct) StoreBountyId(client *ethclient.Client, account types.Accoun } //saving the updated bountyIds to disputeData file + log.Debug("Saving the updated bountyIds to dispute data file...") err = razorUtils.SaveDataToDisputeJsonFile(disputeFilePath, disputeData.BountyIdQueue) if err != nil { return err @@ -423,17 +523,19 @@ func (*UtilsStruct) StoreBountyId(client *ethclient.Client, account types.Accoun //This function resets the dispute func (*UtilsStruct) ResetDispute(client *ethclient.Client, blockManager *bindings.BlockManager, txnOpts *bind.TransactOpts, epoch uint32) { - log.Info("Resetting the dispute ...") + log.Debug("Executing ResetDispute transaction with arguments epoch = ", epoch) txn, err := blockManagerUtils.ResetDispute(blockManager, txnOpts, epoch) if err != nil { log.Error("error in resetting dispute", err) + return } log.Info("Transaction hash: ", transactionUtils.Hash(txn)) - log.Info("Dispute has been reset") err = razorUtils.WaitForBlockCompletion(client, transactionUtils.Hash(txn).String()) if err != nil { log.Error("Error in WaitForBlockCompletion for resetDispute: ", err) + return } + log.Info("Dispute has been reset") } //This function returns the bountyId from events @@ -443,6 +545,7 @@ func (*UtilsStruct) GetBountyIdFromEvents(client *ethclient.Client, blockNumber log.Error(err) return 0, err } + log.Debug("GetBountyIdFromEvents: Checking for events from block: ", fromBlock) query := ethereum.FilterQuery{ FromBlock: fromBlock, ToBlock: blockNumber, @@ -450,6 +553,7 @@ func (*UtilsStruct) GetBountyIdFromEvents(client *ethclient.Client, blockNumber common.HexToAddress(core.StakeManagerAddress), }, } + log.Debugf("GetBountyIdFromEvents: Query to send in filter logs: %+v", query) logs, err := utils.UtilsInterface.FilterLogsWithRetry(client, query) if err != nil { return 0, err @@ -462,7 +566,7 @@ func (*UtilsStruct) GetBountyIdFromEvents(client *ethclient.Client, blockNumber for _, vLog := range logs { data, unpackErr := abiUtils.Unpack(contractAbi, "Slashed", vLog.Data) if unpackErr != nil { - log.Error(unpackErr) + log.Debug(unpackErr) continue } topics := vLog.Topics @@ -474,5 +578,23 @@ func (*UtilsStruct) GetBountyIdFromEvents(client *ethclient.Client, blockNumber bountyId = data[0].(uint32) } } + log.Debug("GetBountyIdFromEvents: Bounty Id: ", bountyId) return bountyId, nil } + +func (*UtilsStruct) CheckToDoResetDispute(client *ethclient.Client, blockManager *bindings.BlockManager, txnOpts *bind.TransactOpts, epoch uint32, sortedValues []*big.Int) { + // Fetch updated dispute mapping + callOpts := razorUtils.GetOptions() + disputesMapping, err := blockManagerUtils.Disputes(client, &callOpts, epoch, txnOpts.From) + if err != nil { + log.Error("Error in getting disputes mapping: ", disputesMapping) + return + } + log.Debugf("CheckToDoResetDispute: Disputes mapping: %+v", disputesMapping) + log.Debug("CheckToDoResetDispute: Updated Last visited value: ", disputesMapping.LastVisitedValue) + //Checking whether LVV is equal to maximum value in sortedValues, if not equal resetting dispute + if disputesMapping.LastVisitedValue.Cmp(big.NewInt(0)) != 0 && disputesMapping.LastVisitedValue.Cmp(sortedValues[len(sortedValues)-1]) != 0 { + log.Debug("CheckToDoResetDispute: Calling Reset Dispute with arguments epoch = ", epoch) + cmdUtils.ResetDispute(client, blockManager, txnOpts, epoch) + } +} diff --git a/cmd/dispute_test.go b/cmd/dispute_test.go index 4a1d2718..ae54319f 100644 --- a/cmd/dispute_test.go +++ b/cmd/dispute_test.go @@ -37,11 +37,11 @@ func TestDispute(t *testing.T) { blockIndex uint8 proposedBlock bindings.StructsBlock leafId uint16 - sortedValues []*big.Int blockManager *bindings.BlockManager ) type args struct { + sortedValues []*big.Int containsStatus bool positionOfCollectionInBlock *big.Int finalizeDisputeTxn *Types.Transaction @@ -57,6 +57,7 @@ func TestDispute(t *testing.T) { { name: "Test 1: When Dispute function executes successfully", args: args{ + sortedValues: []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3), big.NewInt(5)}, containsStatus: false, finalizeDisputeTxn: &Types.Transaction{}, hash: common.BigToHash(big.NewInt(1)), @@ -66,6 +67,7 @@ func TestDispute(t *testing.T) { { name: "Test 2: When Dispute function executes successfully without executing giveSorted", args: args{ + sortedValues: []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3), big.NewInt(5)}, containsStatus: true, finalizeDisputeTxn: &Types.Transaction{}, hash: common.BigToHash(big.NewInt(1)), @@ -75,14 +77,16 @@ func TestDispute(t *testing.T) { { name: "Test 3: When FinalizeDispute transaction fails", args: args{ + sortedValues: []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3), big.NewInt(5)}, containsStatus: false, finalizeDisputeErr: errors.New("finalizeDispute error"), }, - want: errors.New("finalizeDispute error"), + want: nil, }, { name: "Test 4: When Dispute function executes successfully but there is an error in storing bountyId", args: args{ + sortedValues: []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3), big.NewInt(5)}, containsStatus: false, finalizeDisputeTxn: &Types.Transaction{}, hash: common.BigToHash(big.NewInt(1)), @@ -106,16 +110,18 @@ func TestDispute(t *testing.T) { utilsMock.On("GetBlockManager", mock.AnythingOfType("*ethclient.Client")).Return(blockManager) utilsMock.On("GetTxnOpts", mock.AnythingOfType("types.TransactionOptions")).Return(txnOpts) - cmdUtilsMock.On("GiveSorted", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return() + cmdUtilsMock.On("GiveSorted", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) cmdUtilsMock.On("GetCollectionIdPositionInBlock", mock.Anything, mock.Anything, mock.Anything).Return(tt.args.positionOfCollectionInBlock) blockManagerUtilsMock.On("FinalizeDispute", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.finalizeDisputeTxn, tt.args.finalizeDisputeErr) transactionUtilsMock.On("Hash", mock.Anything).Return(tt.args.hash) cmdUtilsMock.On("StoreBountyId", mock.Anything, mock.Anything).Return(tt.args.storeBountyIdErr) utilsMock.On("WaitForBlockCompletion", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return(nil) + cmdUtilsMock.On("CheckToDoResetDispute", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return() + cmdUtilsMock.On("ResetDispute", mock.AnythingOfType("*ethclient.Client"), mock.Anything, mock.Anything, mock.Anything) utils := &UtilsStruct{} - err := utils.Dispute(client, config, account, epoch, blockIndex, proposedBlock, leafId, sortedValues) + err := utils.Dispute(client, config, account, epoch, blockIndex, proposedBlock, leafId, tt.args.sortedValues) if err == nil || tt.want == nil { if err != tt.want { t.Errorf("Error for Dispute function, got = %v, want = %v", err, tt.want) @@ -140,30 +146,30 @@ func TestHandleDispute(t *testing.T) { var blockNumber *big.Int var rogueData types.Rogue var blockManager *bindings.BlockManager + var backupNodeActionsToIgnore []string type args struct { - sortedProposedBlockIds []uint32 - sortedProposedBlockIdsErr error - biggestStake *big.Int - biggestStakeId uint32 - biggestStakeErr error - randomSortedProposedBlockIds []uint32 - medians []*big.Int - revealedCollectionIds []uint16 - revealedDataMaps *types.RevealedDataMaps - mediansErr error - proposedBlock bindings.StructsBlock - proposedBlockErr error - disputeBiggestStakeTxn *Types.Transaction - disputeBiggestStakeErr error - Hash common.Hash - idDisputeTxn *Types.Transaction - idDisputeTxnErr error - misMatchIndex int - leafId uint16 - leafIdErr error - disputeErr error - storeBountyIdErr error + sortedProposedBlockIds []uint32 + sortedProposedBlockIdsErr error + biggestStake *big.Int + biggestStakeId uint32 + biggestStakeErr error + medians []*big.Int + revealedCollectionIds []uint16 + revealedDataMaps *types.RevealedDataMaps + mediansErr error + proposedBlock bindings.StructsBlock + proposedBlockErr error + disputeBiggestStakeTxn *Types.Transaction + disputeBiggestStakeErr error + Hash common.Hash + idDisputeTxn *Types.Transaction + idDisputeTxnErr error + misMatchIndex int + leafId uint16 + leafIdErr error + disputeErr error + storeBountyIdErr error } tests := []struct { name string @@ -173,12 +179,11 @@ func TestHandleDispute(t *testing.T) { { name: "Test 1: When HandleDispute function executes successfully", args: args{ - sortedProposedBlockIds: []uint32{3, 1, 2, 0, 4}, - randomSortedProposedBlockIds: []uint32{2, 3, 1, 4, 0}, - biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), - biggestStakeId: 2, - medians: []*big.Int{big.NewInt(6901548), big.NewInt(498307)}, - revealedCollectionIds: []uint16{1}, + sortedProposedBlockIds: []uint32{3, 1, 2, 0, 4}, + biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), + biggestStakeId: 2, + medians: []*big.Int{big.NewInt(6901548), big.NewInt(498307)}, + revealedCollectionIds: []uint16{1}, revealedDataMaps: &types.RevealedDataMaps{ SortedRevealedValues: nil, VoteWeights: nil, @@ -196,10 +201,9 @@ func TestHandleDispute(t *testing.T) { { name: "Test 2: When HandleDispute function executes successfully when there is no dispute case", args: args{ - sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, - randomSortedProposedBlockIds: []uint32{23, 64, 12, 65, 23}, - biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), - biggestStakeId: 2, + sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, + biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), + biggestStakeId: 2, proposedBlock: bindings.StructsBlock{ Medians: []*big.Int{big.NewInt(6701548), big.NewInt(478307)}, BiggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), @@ -222,20 +226,18 @@ func TestHandleDispute(t *testing.T) { { name: "Test 4: When there is an error in getting proposedBlock", args: args{ - sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, - randomSortedProposedBlockIds: []uint32{23, 64, 12, 65, 23}, - proposedBlockErr: errors.New("proposedBlock error"), - disputeErr: nil, + sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, + proposedBlockErr: errors.New("proposedBlock error"), + disputeErr: nil, }, want: nil, }, { name: "Test 5: When there is a case of Dispute but block is already disputed", args: args{ - sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, - randomSortedProposedBlockIds: []uint32{23, 64, 12, 65, 23}, - biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), - biggestStakeId: 2, + sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, + biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), + biggestStakeId: 2, proposedBlock: bindings.StructsBlock{ Medians: []*big.Int{big.NewInt(6701548), big.NewInt(478307)}, BiggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), @@ -246,10 +248,9 @@ func TestHandleDispute(t *testing.T) { { name: "Test 6: When HandleDispute function executes successfully when there is a biggest influence dispute case", args: args{ - sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, - randomSortedProposedBlockIds: []uint32{23, 64, 12, 65, 23}, - biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), - biggestStakeId: 2, + sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, + biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), + biggestStakeId: 2, proposedBlock: bindings.StructsBlock{ Medians: []*big.Int{big.NewInt(6701548), big.NewInt(478307)}, Valid: true, @@ -264,9 +265,8 @@ func TestHandleDispute(t *testing.T) { { name: "Test 7: When there is an error in getting biggestInfluenceAndId", args: args{ - sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, - randomSortedProposedBlockIds: []uint32{23, 64, 12, 65, 23}, - biggestStakeErr: errors.New("biggestInfluenceAndIdErr"), + sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, + biggestStakeErr: errors.New("biggestInfluenceAndIdErr"), proposedBlock: bindings.StructsBlock{ Medians: []*big.Int{big.NewInt(6701548), big.NewInt(478307)}, Valid: true, @@ -282,10 +282,9 @@ func TestHandleDispute(t *testing.T) { { name: "Test 8: When DisputeBiggestStakeProposed transaction fails", args: args{ - sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, - randomSortedProposedBlockIds: []uint32{23, 64, 12, 65, 23}, - biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), - biggestStakeId: 2, + sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, + biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), + biggestStakeId: 2, proposedBlock: bindings.StructsBlock{ Medians: []*big.Int{big.NewInt(6701548), big.NewInt(478307)}, Valid: true, @@ -300,23 +299,21 @@ func TestHandleDispute(t *testing.T) { { name: "Test 9: When there is an error in getting medians", args: args{ - sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, - randomSortedProposedBlockIds: []uint32{23, 64, 12, 65, 23}, - biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), - biggestStakeId: 2, - mediansErr: errors.New("error in getting medians"), + sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, + biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), + biggestStakeId: 2, + mediansErr: errors.New("error in getting medians"), }, want: errors.New("error in getting medians"), }, { name: "Test 10: When there is an error in fetching Ids from CheckDisputeForIds", args: args{ - sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, - randomSortedProposedBlockIds: []uint32{23, 64, 12, 65, 23}, - biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), - biggestStakeId: 2, - medians: []*big.Int{big.NewInt(6901548), big.NewInt(498307)}, - revealedCollectionIds: []uint16{1}, + sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, + biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), + biggestStakeId: 2, + medians: []*big.Int{big.NewInt(6901548), big.NewInt(498307)}, + revealedCollectionIds: []uint16{1}, revealedDataMaps: &types.RevealedDataMaps{ SortedRevealedValues: nil, VoteWeights: nil, @@ -335,12 +332,11 @@ func TestHandleDispute(t *testing.T) { { name: "Test 11: When idDisputeTxn is not nil", args: args{ - sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, - randomSortedProposedBlockIds: []uint32{23, 64, 12, 65, 23}, - biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), - biggestStakeId: 2, - medians: []*big.Int{big.NewInt(6901548), big.NewInt(498307)}, - revealedCollectionIds: []uint16{1}, + sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, + biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), + biggestStakeId: 2, + medians: []*big.Int{big.NewInt(6901548), big.NewInt(498307)}, + revealedCollectionIds: []uint16{1}, revealedDataMaps: &types.RevealedDataMaps{ SortedRevealedValues: nil, VoteWeights: nil, @@ -359,12 +355,11 @@ func TestHandleDispute(t *testing.T) { { name: "Test 12: When it is a median dispute case and error in getting leafId", args: args{ - sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, - randomSortedProposedBlockIds: []uint32{23, 64, 12, 65, 23}, - biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), - biggestStakeId: 2, - medians: []*big.Int{big.NewInt(6901548), big.NewInt(498307)}, - revealedCollectionIds: []uint16{1}, + sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, + biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), + biggestStakeId: 2, + medians: []*big.Int{big.NewInt(6901548), big.NewInt(498307)}, + revealedCollectionIds: []uint16{1}, revealedDataMaps: &types.RevealedDataMaps{ SortedRevealedValues: nil, VoteWeights: nil, @@ -385,12 +380,11 @@ func TestHandleDispute(t *testing.T) { { name: "Test 13: When there is an error in dispute", args: args{ - sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, - randomSortedProposedBlockIds: []uint32{23, 64, 12, 65, 23}, - biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), - biggestStakeId: 2, - medians: []*big.Int{big.NewInt(6901548), big.NewInt(498307)}, - revealedCollectionIds: []uint16{1}, + sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, + biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), + biggestStakeId: 2, + medians: []*big.Int{big.NewInt(6901548), big.NewInt(498307)}, + revealedCollectionIds: []uint16{1}, revealedDataMaps: &types.RevealedDataMaps{ SortedRevealedValues: nil, VoteWeights: nil, @@ -411,10 +405,9 @@ func TestHandleDispute(t *testing.T) { { name: "Test 14: When there is a biggest influence dispute case but there is an error in storing bountyId", args: args{ - sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, - randomSortedProposedBlockIds: []uint32{23, 64, 12, 65, 23}, - biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), - biggestStakeId: 2, + sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, + biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), + biggestStakeId: 2, proposedBlock: bindings.StructsBlock{ Medians: []*big.Int{big.NewInt(6701548), big.NewInt(478307)}, Valid: true, @@ -430,12 +423,11 @@ func TestHandleDispute(t *testing.T) { { name: "Test 15: When there is a idsDispute case but there is an error in storing bountyId", args: args{ - sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, - randomSortedProposedBlockIds: []uint32{23, 64, 12, 65, 23}, - biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), - biggestStakeId: 2, - medians: []*big.Int{big.NewInt(6901548), big.NewInt(498307)}, - revealedCollectionIds: []uint16{1}, + sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, + biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), + biggestStakeId: 2, + medians: []*big.Int{big.NewInt(6901548), big.NewInt(498307)}, + revealedCollectionIds: []uint16{1}, revealedDataMaps: &types.RevealedDataMaps{ SortedRevealedValues: nil, VoteWeights: nil, @@ -455,12 +447,11 @@ func TestHandleDispute(t *testing.T) { { name: "Test 16: When HandleDispute function executes successfully and medians proposed are empty", args: args{ - sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, - randomSortedProposedBlockIds: []uint32{23, 64, 12, 65, 23}, - biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), - biggestStakeId: 2, - medians: []*big.Int{big.NewInt(6901548), big.NewInt(498307)}, - revealedCollectionIds: []uint16{1}, + sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, + biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), + biggestStakeId: 2, + medians: []*big.Int{big.NewInt(6901548), big.NewInt(498307)}, + revealedCollectionIds: []uint16{1}, revealedDataMaps: &types.RevealedDataMaps{ SortedRevealedValues: nil, VoteWeights: nil, @@ -478,12 +469,11 @@ func TestHandleDispute(t *testing.T) { { name: "Test 17: When there is a case of blockIndex = -1", args: args{ - sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, - randomSortedProposedBlockIds: []uint32{23, 64, 12, 65, 23}, - biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), - biggestStakeId: 2, - medians: []*big.Int{big.NewInt(6901548), big.NewInt(498307)}, - revealedCollectionIds: []uint16{1}, + sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, + biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), + biggestStakeId: 2, + medians: []*big.Int{big.NewInt(6901548), big.NewInt(498307)}, + revealedCollectionIds: []uint16{1}, revealedDataMaps: &types.RevealedDataMaps{ SortedRevealedValues: nil, VoteWeights: nil, @@ -501,12 +491,11 @@ func TestHandleDispute(t *testing.T) { { name: "Test 18: When HandleDispute function executes successfully and contains different values in sortedProposedBlockIds", args: args{ - sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, - randomSortedProposedBlockIds: []uint32{23, 64, 12, 65, 23}, - biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), - biggestStakeId: 2, - medians: []*big.Int{big.NewInt(6901548), big.NewInt(498307)}, - revealedCollectionIds: []uint16{1}, + sortedProposedBlockIds: []uint32{45, 65, 23, 64, 12}, + biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), + biggestStakeId: 2, + medians: []*big.Int{big.NewInt(6901548), big.NewInt(498307)}, + revealedCollectionIds: []uint16{1}, revealedDataMaps: &types.RevealedDataMaps{ SortedRevealedValues: nil, VoteWeights: nil, @@ -541,8 +530,11 @@ func TestHandleDispute(t *testing.T) { utilsMock.On("GetSortedProposedBlockIds", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32")).Return(tt.args.sortedProposedBlockIds, tt.args.sortedProposedBlockIdsErr) cmdUtilsMock.On("GetBiggestStakeAndId", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string"), mock.AnythingOfType("uint32")).Return(tt.args.biggestStake, tt.args.biggestStakeId, tt.args.biggestStakeErr) - cmdUtilsMock.On("GetLocalMediansData", mock.AnythingOfType("*ethclient.Client"), mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.medians, tt.args.revealedCollectionIds, tt.args.revealedDataMaps, tt.args.mediansErr) - utilsPkgMock.On("Shuffle", mock.Anything).Return(tt.args.randomSortedProposedBlockIds) + cmdUtilsMock.On("GetLocalMediansData", mock.AnythingOfType("*ethclient.Client"), mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(types.ProposeFileData{ + MediansData: tt.args.medians, + RevealedCollectionIds: tt.args.revealedCollectionIds, + RevealedDataMaps: tt.args.revealedDataMaps, + }, tt.args.mediansErr) utilsMock.On("GetProposedBlock", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32"), mock.AnythingOfType("uint32")).Return(tt.args.proposedBlock, tt.args.proposedBlockErr) utilsMock.On("GetTxnOpts", mock.AnythingOfType("types.TransactionOptions")).Return(txnOpts) blockManagerUtilsMock.On("DisputeBiggestStakeProposed", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.disputeBiggestStakeTxn, tt.args.disputeBiggestStakeErr) @@ -556,7 +548,7 @@ func TestHandleDispute(t *testing.T) { cmdUtilsMock.On("ResetDispute", mock.AnythingOfType("*ethclient.Client"), mock.Anything, mock.Anything, mock.Anything) utils := &UtilsStruct{} - err := utils.HandleDispute(client, config, account, epoch, blockNumber, rogueData) + err := utils.HandleDispute(client, config, account, epoch, blockNumber, rogueData, backupNodeActionsToIgnore) if err == nil || tt.want == nil { if err != tt.want { t.Errorf("Error for HandleDispute function, got = %v, want = %v", err, tt.want) @@ -571,59 +563,98 @@ func TestHandleDispute(t *testing.T) { } func TestGiveSorted(t *testing.T) { + privateKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + txnOpts, _ := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(31337)) + + nilDisputesMapping := types.DisputesStruct{ + LastVisitedValue: big.NewInt(0), + Median: big.NewInt(0), + AccWeight: big.NewInt(0), + } + var client *ethclient.Client var blockManager *bindings.BlockManager - var txnOpts *bind.TransactOpts + var txnArgs types.TransactionOptions var epoch uint32 - var assetId uint16 + var callOpts bind.CallOpts + type args struct { - sortedValues []*big.Int - giveSorted *Types.Transaction - giveSortedErr error - hash common.Hash + leafId uint16 + disputesMapping types.DisputesStruct + disputesMappingErr error + sortedValues []*big.Int + giveSorted *Types.Transaction + giveSortedErr error + hash common.Hash + waitForBlockCompletionErr error } tests := []struct { - name string - args args + name string + args args + wantErr bool }{ { name: "Test 1: When Give Sorted executes successfully", args: args{ - sortedValues: []*big.Int{big.NewInt(2), big.NewInt(1), big.NewInt(3), big.NewInt(5)}, - giveSorted: &Types.Transaction{}, - hash: common.BigToHash(big.NewInt(1)), + leafId: 0, + disputesMapping: nilDisputesMapping, + sortedValues: []*big.Int{big.NewInt(2), big.NewInt(1), big.NewInt(3), big.NewInt(5)}, + giveSorted: &Types.Transaction{}, + hash: common.BigToHash(big.NewInt(1)), }, + wantErr: false, }, { name: "Test 2: When there is an error from GiveSorted", args: args{ - sortedValues: []*big.Int{big.NewInt(2), big.NewInt(1), big.NewInt(3), big.NewInt(5)}, - giveSortedErr: errors.New("giveSorted error"), + leafId: 0, + disputesMapping: nilDisputesMapping, + sortedValues: []*big.Int{big.NewInt(2), big.NewInt(1), big.NewInt(3), big.NewInt(5)}, + giveSortedErr: errors.New("giveSorted error"), }, + wantErr: true, }, { name: "Test 3: When sortedStakers is nil", args: args{ + leafId: 0, sortedValues: nil, }, + wantErr: true, + }, + { + name: "Test 4: When there is an error in getting disputesMapping", + args: args{ + leafId: 0, + disputesMappingErr: errors.New("disputesMapping error"), + sortedValues: []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3), big.NewInt(5)}, + }, + wantErr: true, }, { - name: "Test 4: When error is gas limit reached", + name: "Test 5: When there is already giveSorted in progress", args: args{ - sortedValues: []*big.Int{big.NewInt(2), big.NewInt(1), big.NewInt(3), big.NewInt(5)}, - giveSortedErr: errors.New("gas limit reached"), - giveSorted: &Types.Transaction{}, - hash: common.BigToHash(big.NewInt(1)), + leafId: 1, + disputesMapping: types.DisputesStruct{ + LastVisitedValue: big.NewInt(1), + AccWeight: big.NewInt(200), + LeafId: 0, + }, + sortedValues: []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3), big.NewInt(5)}, }, + wantErr: true, }, { - name: "Test 5: When error is gas limit reached with higher number of stakers", + name: "Test 6: When waitForBlockCompletion throws an error", args: args{ - sortedValues: []*big.Int{big.NewInt(2), big.NewInt(1), big.NewInt(3), big.NewInt(5), big.NewInt(7), big.NewInt(8), big.NewInt(9), big.NewInt(10), big.NewInt(6), big.NewInt(11), big.NewInt(13), big.NewInt(12), big.NewInt(14), big.NewInt(15), big.NewInt(4), big.NewInt(20), big.NewInt(19), big.NewInt(18), big.NewInt(17), big.NewInt(16)}, - giveSortedErr: errors.New("gas limit reached"), - giveSorted: &Types.Transaction{}, - hash: common.BigToHash(big.NewInt(1)), + leafId: 0, + disputesMapping: nilDisputesMapping, + sortedValues: []*big.Int{big.NewInt(2), big.NewInt(1), big.NewInt(3), big.NewInt(5)}, + giveSorted: &Types.Transaction{}, + hash: common.BigToHash(big.NewInt(1)), + waitForBlockCompletionErr: errors.New("waitForBlockCompletion error"), }, + wantErr: true, }, } for _, tt := range tests { @@ -631,17 +662,27 @@ func TestGiveSorted(t *testing.T) { utilsMock := new(mocks.UtilsInterface) blockManagerUtilsMock := new(mocks.BlockManagerInterface) transactionUtilsMock := new(mocks.TransactionInterface) + cmdUtilsMock := new(mocks.UtilsCmdInterface) razorUtils = utilsMock blockManagerUtils = blockManagerUtilsMock transactionUtils = transactionUtilsMock + cmdUtils = cmdUtilsMock blockManagerUtilsMock.On("GiveSorted", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.giveSorted, tt.args.giveSortedErr).Once() transactionUtilsMock.On("Hash", mock.Anything).Return(tt.args.hash) - utilsMock.On("WaitForBlockCompletion", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return(nil) + utilsMock.On("WaitForBlockCompletion", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return(tt.args.waitForBlockCompletionErr) + utilsMock.On("GetOptions").Return(callOpts) + blockManagerUtilsMock.On("Disputes", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.disputesMapping, tt.args.disputesMappingErr) + utilsMock.On("GetTxnOpts", mock.AnythingOfType("types.TransactionOptions")).Return(txnOpts) blockManagerUtilsMock.On("GiveSorted", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.giveSorted, nil) + cmdUtilsMock.On("ResetDispute", mock.AnythingOfType("*ethclient.Client"), mock.Anything, mock.Anything, mock.Anything) - GiveSorted(client, blockManager, txnOpts, epoch, assetId, tt.args.sortedValues) + err := GiveSorted(client, blockManager, txnArgs, epoch, tt.args.leafId, tt.args.sortedValues) + if (err != nil) != tt.wantErr { + t.Errorf("CheckDisputeForIds() error = %v, wantErr %v", err, tt.wantErr) + return + } }) } } @@ -772,21 +813,21 @@ func TestGetLocalMediansData(t *testing.T) { utilsMock.On("ReadFromProposeJsonFile", mock.Anything).Return(tt.args.proposedData, tt.args.proposeDataErr) cmdUtilsMock.On("MakeBlock", mock.AnythingOfType("*ethclient.Client"), mock.Anything, mock.Anything, mock.Anything).Return(tt.args.medians, tt.args.revealedCollectionIds, tt.args.revealedDataMaps, tt.args.mediansErr) utilsMock.On("GetStakerId", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return(tt.args.stakerId, tt.args.stakerIdErr) - cmdUtilsMock.On("GetLastProposedEpoch", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("*big.Int"), mock.AnythingOfType("uint32")).Return(tt.args.lastProposedEpoch, tt.args.lastProposedEpochErr) + utilsMock.On("GetEpochLastProposed", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32")).Return(tt.args.lastProposedEpoch, tt.args.lastProposedEpochErr) ut := &UtilsStruct{} - got, got1, got2, err := ut.GetLocalMediansData(client, account, tt.args.epoch, blockNumber, rogueData) + localProposedData, err := ut.GetLocalMediansData(client, account, tt.args.epoch, blockNumber, rogueData) if (err != nil) != tt.wantErr { t.Errorf("GetLocalMediansData() error = %v, wantErr %v", err, tt.wantErr) return } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetLocalMediansData() got = %v, want %v", got, tt.want) + if !reflect.DeepEqual(localProposedData.MediansData, tt.want) { + t.Errorf("GetLocalMediansData() got = %v, want %v", localProposedData.MediansData, tt.want) } - if !reflect.DeepEqual(got1, tt.want1) { - t.Errorf("GetLocalMediansData() got1 = %v, want %v", got1, tt.want1) + if !reflect.DeepEqual(localProposedData.RevealedCollectionIds, tt.want1) { + t.Errorf("GetLocalMediansData() got1 = %v, want %v", localProposedData.RevealedCollectionIds, tt.want1) } - if !reflect.DeepEqual(got2, tt.want2) { - t.Errorf("GetLocalMediansData() got2 = %v, want %v", got2, tt.want2) + if !reflect.DeepEqual(localProposedData.RevealedDataMaps, tt.want2) { + t.Errorf("GetLocalMediansData() got2 = %v, want %v", localProposedData.RevealedDataMaps, tt.want2) } }) } @@ -1173,7 +1214,7 @@ func BenchmarkHandleDispute(b *testing.B) { var blockNumber *big.Int var rogueData types.Rogue var blockManager *bindings.BlockManager - var randomSortedPorposedBlockIds []uint32 + var backupNodeActionsToIgnore []string table := []struct { numOfSortedBlocks uint32 @@ -1205,6 +1246,11 @@ func BenchmarkHandleDispute(b *testing.B) { SortedRevealedValues: nil, VoteWeights: nil, InfluenceSum: nil} + proposedData := types.ProposeFileData{ + MediansData: medians, + RevealedCollectionIds: revealedCollectionIds, + RevealedDataMaps: revealedDataMaps, + } proposedBlock := bindings.StructsBlock{ Medians: []*big.Int{big.NewInt(6901548), big.NewInt(498307)}, Valid: true, @@ -1212,8 +1258,7 @@ func BenchmarkHandleDispute(b *testing.B) { utilsMock.On("GetSortedProposedBlockIds", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32")).Return(getUint32DummyIds(v.numOfSortedBlocks), nil) cmdUtilsMock.On("GetBiggestStakeAndId", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string"), mock.AnythingOfType("uint32")).Return(big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), uint32(2), nil) - cmdUtilsMock.On("GetLocalMediansData", mock.AnythingOfType("*ethclient.Client"), mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(medians, revealedCollectionIds, revealedDataMaps, nil) - utilsPkgMock.On("Shuffle", mock.Anything).Return(randomSortedPorposedBlockIds) + cmdUtilsMock.On("GetLocalMediansData", mock.AnythingOfType("*ethclient.Client"), mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(proposedData, nil) utilsMock.On("GetProposedBlock", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32"), mock.AnythingOfType("uint32")).Return(proposedBlock, nil) utilsMock.On("GetTxnOpts", mock.AnythingOfType("types.TransactionOptions")).Return(txnOpts) blockManagerUtilsMock.On("DisputeBiggestStakeProposed", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&Types.Transaction{}, nil) @@ -1225,10 +1270,9 @@ func BenchmarkHandleDispute(b *testing.B) { cmdUtilsMock.On("Dispute", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) utilsMock.On("GetBlockManager", mock.AnythingOfType("*ethclient.Client")).Return(blockManager) cmdUtilsMock.On("StoreBountyId", mock.Anything, mock.Anything).Return(nil) - cmdUtilsMock.On("ResetDispute", mock.AnythingOfType("*ethclient.Client"), mock.Anything, mock.Anything, mock.Anything) utils := &UtilsStruct{} - err := utils.HandleDispute(client, config, account, epoch, blockNumber, rogueData) + err := utils.HandleDispute(client, config, account, epoch, blockNumber, rogueData, backupNodeActionsToIgnore) if err != nil { log.Fatal(err) } diff --git a/cmd/import.go b/cmd/import.go index 5374e235..12eaa9e9 100644 --- a/cmd/import.go +++ b/cmd/import.go @@ -28,15 +28,18 @@ func initialiseImport(cmd *cobra.Command, args []string) { //This function sets the flags appropriately and executes the ImportAccount function func (*UtilsStruct) ExecuteImport(flagSet *pflag.FlagSet) { + log.Debug("Checking to assign log file...") razorUtils.AssignLogFile(flagSet) + log.Debug("Calling ImportAccount()...") account, err := cmdUtils.ImportAccount() utils.CheckError("Import error: ", err) - log.Info("Account Address: ", account.Address) - log.Info("Keystore Path: ", account.URL) + log.Info("ExecuteImport: Account Address: ", account.Address) + log.Info("ExecuteImport: Keystore Path: ", account.URL) } //This function is used to import existing accounts into razor-go func (*UtilsStruct) ImportAccount() (accounts.Account, error) { + log.Info("Enter the private key for the account that you want to import") privateKey := razorUtils.PrivateKeyPrompt() // Remove 0x from the private key privateKey = strings.TrimPrefix(privateKey, "0x") @@ -48,6 +51,7 @@ func (*UtilsStruct) ImportAccount() (accounts.Account, error) { log.Error("Error in fetching .razor directory") return accounts.Account{Address: common.Address{0x00}}, err } + log.Debug("ImportAccount: .razor directory path: ", razorPath) priv, err := cryptoUtils.HexToECDSA(privateKey) if err != nil { log.Error("Error in parsing private key") @@ -60,6 +64,8 @@ func (*UtilsStruct) ImportAccount() (accounts.Account, error) { return accounts.Account{Address: common.Address{0x00}}, mkdirErr } } + log.Debug("ImportAccount: Keystore directory path: ", keystoreDir) + log.Debug("Importing the account...") account, err := keystoreUtils.ImportECDSA(keystoreDir, priv, password) if err != nil { log.Error("Error in importing account") diff --git a/cmd/initiateWithdraw.go b/cmd/initiateWithdraw.go index d8994666..1d2226ec 100644 --- a/cmd/initiateWithdraw.go +++ b/cmd/initiateWithdraw.go @@ -3,17 +3,18 @@ package cmd import ( "errors" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/spf13/cobra" - "github.com/spf13/pflag" "math/big" "razor/core" "razor/core/types" "razor/logger" "razor/pkg/bindings" "razor/utils" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/spf13/cobra" + "github.com/spf13/pflag" ) var initiateWithdrawCmd = &cobra.Command{ @@ -33,22 +34,28 @@ Example: func (*UtilsStruct) ExecuteInitiateWithdraw(flagSet *pflag.FlagSet) { config, err := cmdUtils.GetConfigData() utils.CheckError("Error in getting config: ", err) + log.Debugf("ExecuteInitiateWithdraw: Config: %+v: ", config) client := razorUtils.ConnectToClient(config.Provider) address, err := flagSetUtils.GetStringAddress(flagSet) utils.CheckError("Error in getting address: ", err) + log.Debug("ExecuteInitiateWithdraw: Address: ", address) logger.SetLoggerParameters(client, address) + log.Debug("Checking to assign log file...") razorUtils.AssignLogFile(flagSet) - password := razorUtils.AssignPassword() + log.Debug("Getting password...") + password := razorUtils.AssignPassword(flagSet) razorUtils.CheckEthBalanceIsZero(client, address) stakerId, err := razorUtils.AssignStakerId(flagSet, client, address) utils.CheckError("Error in fetching stakerId: ", err) + log.Debug("ExecuteInitiateWithdraw: Staker Id: ", stakerId) + log.Debugf("ExecuteInitiateWithdraw: Calling HandleUnstakeLock() with arguments account address: %s, stakerId: %d", address, stakerId) txn, err := cmdUtils.HandleUnstakeLock(client, types.Account{ Address: address, Password: password, @@ -63,7 +70,6 @@ func (*UtilsStruct) ExecuteInitiateWithdraw(flagSet *pflag.FlagSet) { //This function handles the unstake lock func (*UtilsStruct) HandleUnstakeLock(client *ethclient.Client, account types.Account, configurations types.Configurations, stakerId uint32) (common.Hash, error) { - _, err := cmdUtils.WaitForAppropriateState(client, "initiateWithdraw", 0, 1, 4) if err != nil { log.Error("Error in fetching epoch: ", err) @@ -75,6 +81,7 @@ func (*UtilsStruct) HandleUnstakeLock(client *ethclient.Client, account types.Ac log.Error("Error in fetching unstakeLock") return core.NilHash, err } + log.Debugf("HandleUnstakeLock: Unstake lock: %+v", unstakeLock) if unstakeLock.UnlockAfter.Cmp(big.NewInt(0)) == 0 { log.Error("Unstake command not called before initiating withdrawal!") @@ -86,13 +93,16 @@ func (*UtilsStruct) HandleUnstakeLock(client *ethclient.Client, account types.Ac log.Error("Error in fetching withdraw release period") return core.NilHash, err } + log.Debug("HandleUnstakeLock: Withdraw initiation period: ", withdrawInitiationPeriod) withdrawBefore := big.NewInt(0).Add(unstakeLock.UnlockAfter, big.NewInt(int64(withdrawInitiationPeriod))) + log.Debug("HandleUnstakeLock: Withdraw before epoch: ", withdrawBefore) epoch, err := razorUtils.GetEpoch(client) if err != nil { log.Error("Error in fetching epoch") return core.NilHash, err } + log.Debug("HandleUnstakeLock: Current epoch: ", epoch) if big.NewInt(int64(epoch)).Cmp(withdrawBefore) > 0 { log.Info("Withdraw initiation period has passed. Cannot withdraw now, please reset the unstakeLock!") @@ -124,6 +134,7 @@ func (*UtilsStruct) HandleUnstakeLock(client *ethclient.Client, account types.Ac txnOpts := razorUtils.GetTxnOpts(txnArgs) if big.NewInt(int64(epoch)).Cmp(unstakeLock.UnlockAfter) >= 0 && big.NewInt(int64(epoch)).Cmp(withdrawBefore) <= 0 { + log.Debug("Calling InitiateWithdraw() with arguments stakerId: ", stakerId) return cmdUtils.InitiateWithdraw(client, txnOpts, stakerId) } return core.NilHash, errors.New("unstakeLock period not over yet! Please try after some time") @@ -132,7 +143,7 @@ func (*UtilsStruct) HandleUnstakeLock(client *ethclient.Client, account types.Ac //This function initiate withdraw for your razors once you've unstaked func (*UtilsStruct) InitiateWithdraw(client *ethclient.Client, txnOpts *bind.TransactOpts, stakerId uint32) (common.Hash, error) { log.Info("Initiating withdrawal of funds...") - + log.Debug("Executing InitiateWithdraw transaction for stakerId = ", stakerId) txn, err := stakeManagerUtils.InitiateWithdraw(client, txnOpts, stakerId) if err != nil { log.Error("Error in initiating withdrawal of funds") @@ -149,10 +160,12 @@ func init() { var ( Address string + Password string StakerId uint32 ) initiateWithdrawCmd.Flags().StringVarP(&Address, "address", "a", "", "address of the user") + initiateWithdrawCmd.Flags().StringVarP(&Password, "password", "", "", "password path of user to protect the keystore") initiateWithdrawCmd.Flags().Uint32VarP(&StakerId, "stakerId", "", 0, "password path of user to protect the keystore") addrErr := initiateWithdrawCmd.MarkFlagRequired("address") diff --git a/cmd/initiateWithdraw_test.go b/cmd/initiateWithdraw_test.go index 087f9494..fe2472f8 100644 --- a/cmd/initiateWithdraw_test.go +++ b/cmd/initiateWithdraw_test.go @@ -423,7 +423,7 @@ func TestExecuteWithdraw(t *testing.T) { utilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet")) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) - utilsMock.On("AssignPassword").Return(tt.args.password) + utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) flagSetUtilsMock.On("GetStringAddress", flagSet).Return(tt.args.address, tt.args.addressErr) utilsMock.On("CheckEthBalanceIsZero", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return() utilsMock.On("AssignStakerId", flagSet, mock.AnythingOfType("*ethclient.Client"), mock.Anything).Return(tt.args.stakerId, tt.args.stakerIdErr) diff --git a/cmd/interface.go b/cmd/interface.go index 29cd8b1d..500bb926 100644 --- a/cmd/interface.go +++ b/cmd/interface.go @@ -60,7 +60,7 @@ type UtilsInterface interface { GetOptions() bind.CallOpts CalculateBlockTime(client *ethclient.Client) int64 GetTxnOpts(transactionData types.TransactionOptions) *bind.TransactOpts - AssignPassword() string + AssignPassword(flagSet *pflag.FlagSet) string GetStringAddress(flagSet *pflag.FlagSet) (string, error) GetUint32BountyId(flagSet *pflag.FlagSet) (uint32, error) ConnectToClient(provider string) *ethclient.Client @@ -119,7 +119,7 @@ type UtilsInterface interface { SecondsToReadableTime(time int) string SaveDataToCommitJsonFile(flePath string, epoch uint32, commitFileData types.CommitData) error ReadFromCommitJsonFile(filePath string) (types.CommitFileData, error) - SaveDataToProposeJsonFile(flePath string, epoch uint32, proposeFileData types.ProposeData) error + SaveDataToProposeJsonFile(flePath string, proposeFileData types.ProposeFileData) error ReadFromProposeJsonFile(filePath string) (types.ProposeFileData, error) SaveDataToDisputeJsonFile(filePath string, bountyIdQueue []uint32) error ReadFromDisputeJsonFile(filePath string) (types.DisputeFileData, error) @@ -127,6 +127,7 @@ type UtilsInterface interface { GetCommitDataFileName(address string) (string, error) GetProposeDataFileName(address string) (string, error) GetDisputeDataFileName(address string) (string, error) + GetEpochLastProposed(client *ethclient.Client, stakerId uint32) (uint32, error) } type StakeManagerInterface interface { @@ -163,6 +164,7 @@ type BlockManagerInterface interface { DisputeCollectionIdShouldBePresent(client *ethclient.Client, opts *bind.TransactOpts, epoch uint32, blockIndex uint8, id uint16) (*Types.Transaction, error) GiveSorted(blockManager *bindings.BlockManager, opts *bind.TransactOpts, epoch uint32, leafId uint16, sortedValues []*big.Int) (*Types.Transaction, error) ResetDispute(blockManager *bindings.BlockManager, opts *bind.TransactOpts, epoch uint32) (*Types.Transaction, error) + Disputes(client *ethclient.Client, opts *bind.CallOpts, epoch uint32, address common.Address) (types.DisputesStruct, error) } type VoteManagerInterface interface { @@ -193,6 +195,7 @@ type FlagSetInterface interface { GetInt32GasPrice(flagSet *pflag.FlagSet) (int32, error) GetFloat32GasLimit(flagSet *pflag.FlagSet) (float32, error) GetStringLogLevel(flagSet *pflag.FlagSet) (string, error) + GetInt64RPCTimeout(flagSet *pflag.FlagSet) (int64, error) GetUint32BountyId(flagSet *pflag.FlagSet) (uint32, error) GetRootStringProvider() (string, error) GetRootFloat32GasMultiplier() (float32, error) @@ -201,6 +204,7 @@ type FlagSetInterface interface { GetRootInt32GasPrice() (int32, error) GetRootStringLogLevel() (string, error) GetRootFloat32GasLimit() (float32, error) + GetRootInt64RPCTimeout() (int64, error) GetStringFrom(flagSet *pflag.FlagSet) (string, error) GetStringTo(flagSet *pflag.FlagSet) (string, error) GetStringAddress(flagSet *pflag.FlagSet) (string, error) @@ -223,6 +227,7 @@ type FlagSetInterface interface { GetUint32Tolerance(flagSet *pflag.FlagSet) (uint32, error) GetBoolRogue(flagSet *pflag.FlagSet) (bool, error) GetStringSliceRogueMode(flagSet *pflag.FlagSet) ([]string, error) + GetStringSliceBackupNode(flagSet *pflag.FlagSet) ([]string, error) GetStringExposeMetrics(flagSet *pflag.FlagSet) (string, error) GetStringCertFile(flagSet *pflag.FlagSet) (string, error) GetStringCertKey(flagSet *pflag.FlagSet) (string, error) @@ -237,6 +242,7 @@ type UtilsCmdInterface interface { GetLogLevel() (string, error) GetGasLimit() (float32, error) GetBufferPercent() (int32, error) + GetRPCTimeout() (int64, error) GetConfigData() (types.Configurations, error) ExecuteClaimBounty(flagSet *pflag.FlagSet) ClaimBounty(config types.Configurations, client *ethclient.Client, redeemBountyInput types.RedeemBountyInput) (common.Hash, error) @@ -285,13 +291,13 @@ type UtilsCmdInterface interface { IsElectedProposer(proposer types.ElectedProposer, currentStakerStake *big.Int) bool GetSortedRevealedValues(client *ethclient.Client, blockNumber *big.Int, epoch uint32) (*types.RevealedDataMaps, error) GetIteration(client *ethclient.Client, proposer types.ElectedProposer, bufferPercent int32) int - Propose(client *ethclient.Client, config types.Configurations, account types.Account, staker bindings.StructsStaker, epoch uint32, blockNumber *big.Int, rogueData types.Rogue) (common.Hash, error) - GiveSorted(client *ethclient.Client, blockManager *bindings.BlockManager, txnOpts *bind.TransactOpts, epoch uint32, assetId uint16, sortedStakers []*big.Int) - GetLocalMediansData(client *ethclient.Client, account types.Account, epoch uint32, blockNumber *big.Int, rogueData types.Rogue) ([]*big.Int, []uint16, *types.RevealedDataMaps, error) + Propose(client *ethclient.Client, config types.Configurations, account types.Account, staker bindings.StructsStaker, epoch uint32, blockNumber *big.Int, rogueData types.Rogue) error + GiveSorted(client *ethclient.Client, blockManager *bindings.BlockManager, txnArgs types.TransactionOptions, epoch uint32, assetId uint16, sortedStakers []*big.Int) error + GetLocalMediansData(client *ethclient.Client, account types.Account, epoch uint32, blockNumber *big.Int, rogueData types.Rogue) (types.ProposeFileData, error) CheckDisputeForIds(client *ethclient.Client, transactionOpts types.TransactionOptions, epoch uint32, blockIndex uint8, idsInProposedBlock []uint16, revealedCollectionIds []uint16) (*Types.Transaction, error) Dispute(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, blockIndex uint8, proposedBlock bindings.StructsBlock, leafId uint16, sortedValues []*big.Int) error GetCollectionIdPositionInBlock(client *ethclient.Client, leafId uint16, proposedBlock bindings.StructsBlock) *big.Int - HandleDispute(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, blockNumber *big.Int, rogueData types.Rogue) error + HandleDispute(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, blockNumber *big.Int, rogueData types.Rogue, backupNodeActionsToIgnore []string) error ExecuteExtendLock(flagSet *pflag.FlagSet) ResetUnstakeLock(client *ethclient.Client, config types.Configurations, extendLockInput types.ExtendLockInput) (common.Hash, error) CheckCurrentStatus(client *ethclient.Client, collectionId uint16) (bool, error) @@ -310,10 +316,9 @@ type UtilsCmdInterface interface { GetSmallestStakeAndId(client *ethclient.Client, epoch uint32) (*big.Int, uint32, error) StakeCoins(txnArgs types.TransactionOptions) (common.Hash, error) CalculateSecret(account types.Account, epoch uint32, keystorePath string, chainId *big.Int) ([]byte, []byte, error) - GetLastProposedEpoch(client *ethclient.Client, blockNumber *big.Int, stakerId uint32) (uint32, error) - HandleBlock(client *ethclient.Client, account types.Account, blockNumber *big.Int, config types.Configurations, rogueData types.Rogue) + HandleBlock(client *ethclient.Client, account types.Account, blockNumber *big.Int, config types.Configurations, rogueData types.Rogue, backupNodeActionsToIgnore []string) ExecuteVote(flagSet *pflag.FlagSet) - Vote(ctx context.Context, config types.Configurations, client *ethclient.Client, rogueData types.Rogue, account types.Account) error + Vote(ctx context.Context, config types.Configurations, client *ethclient.Client, rogueData types.Rogue, account types.Account, backupNodeActionsToIgnore []string) error HandleExit() ExecuteListAccounts(flagSet *pflag.FlagSet) ClaimCommission(flagSet *pflag.FlagSet) @@ -327,6 +332,7 @@ type UtilsCmdInterface interface { ContractAddresses() ResetDispute(client *ethclient.Client, blockManager *bindings.BlockManager, txnOpts *bind.TransactOpts, epoch uint32) StoreBountyId(client *ethclient.Client, account types.Account) error + CheckToDoResetDispute(client *ethclient.Client, blockManager *bindings.BlockManager, txnOpts *bind.TransactOpts, epoch uint32, sortedValues []*big.Int) } type TransactionInterface interface { diff --git a/cmd/jobList.go b/cmd/jobList.go index b886e080..82858323 100644 --- a/cmd/jobList.go +++ b/cmd/jobList.go @@ -32,10 +32,12 @@ func initialiseJobList(cmd *cobra.Command, args []string) { func (*UtilsStruct) ExecuteJobList(flagSet *pflag.FlagSet) { config, err := cmdUtils.GetConfigData() utils.CheckError("Error in getting config: ", err) + log.Debugf("ExecuteJobList: Config: %+v", config) client := razorUtils.ConnectToClient(config.Provider) logger.SetLoggerParameters(client, "") + log.Debug("ExecuteJobList: Calling JobList()...") err = cmdUtils.GetJobList(client) utils.CheckError("Error in getting job list: ", err) } @@ -43,7 +45,7 @@ func (*UtilsStruct) ExecuteJobList(flagSet *pflag.FlagSet) { //This function provides the list of all jobs func (*UtilsStruct) GetJobList(client *ethclient.Client) error { jobs, err := razorUtils.GetJobs(client) - + log.Debugf("JobList: Jobs: %+v", jobs) if err != nil { return err } diff --git a/cmd/listAccounts.go b/cmd/listAccounts.go index 08d72b2b..ebf9469f 100644 --- a/cmd/listAccounts.go +++ b/cmd/listAccounts.go @@ -25,10 +25,12 @@ func initialiseListAccounts(cmd *cobra.Command, args []string) { //This function sets the flag appropriately and executes the ListAccounts function func (*UtilsStruct) ExecuteListAccounts(flagSet *pflag.FlagSet) { + log.Debug("Checking to assign log file...") razorUtils.AssignLogFile(flagSet) + log.Debug("ExecuteListAccounts: Calling ListAccounts()...") allAccounts, err := cmdUtils.ListAccounts() utils.CheckError("ListAccounts error: ", err) - log.Info("The available accounts are: ") + log.Info("ExecuteListAccounts: The available accounts are: ") for _, account := range allAccounts { log.Infof("%s", account.Address.String()) } @@ -41,8 +43,10 @@ func (*UtilsStruct) ListAccounts() ([]accounts.Account, error) { log.Error("Error in fetching .razor directory") return nil, err } + log.Debug("ListAccounts: .razor directory path: ", path) keystorePath := pathPkg.Join(path, "keystore_files") + log.Debug("ListAccounts: Keystore path: ", keystorePath) return keystoreUtils.Accounts(keystorePath), nil } diff --git a/cmd/mocks/block_manager_interface.go b/cmd/mocks/block_manager_interface.go index e28f9327..37fc600a 100644 --- a/cmd/mocks/block_manager_interface.go +++ b/cmd/mocks/block_manager_interface.go @@ -8,6 +8,10 @@ import ( bind "github.com/ethereum/go-ethereum/accounts/abi/bind" + common "github.com/ethereum/go-ethereum/common" + + coretypes "razor/core/types" + ethclient "github.com/ethereum/go-ethereum/ethclient" mock "github.com/stretchr/testify/mock" @@ -135,6 +139,27 @@ func (_m *BlockManagerInterface) DisputeOnOrderOfIds(client *ethclient.Client, o return r0, r1 } +// Disputes provides a mock function with given fields: client, opts, epoch, address +func (_m *BlockManagerInterface) Disputes(client *ethclient.Client, opts *bind.CallOpts, epoch uint32, address common.Address) (coretypes.DisputesStruct, error) { + ret := _m.Called(client, opts, epoch, address) + + var r0 coretypes.DisputesStruct + if rf, ok := ret.Get(0).(func(*ethclient.Client, *bind.CallOpts, uint32, common.Address) coretypes.DisputesStruct); ok { + r0 = rf(client, opts, epoch, address) + } else { + r0 = ret.Get(0).(coretypes.DisputesStruct) + } + + var r1 error + if rf, ok := ret.Get(1).(func(*ethclient.Client, *bind.CallOpts, uint32, common.Address) error); ok { + r1 = rf(client, opts, epoch, address) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // FinalizeDispute provides a mock function with given fields: client, opts, epoch, blockIndex, positionOfCollectionInBlock func (_m *BlockManagerInterface) FinalizeDispute(client *ethclient.Client, opts *bind.TransactOpts, epoch uint32, blockIndex uint8, positionOfCollectionInBlock *big.Int) (*types.Transaction, error) { ret := _m.Called(client, opts, epoch, blockIndex, positionOfCollectionInBlock) diff --git a/cmd/mocks/flag_set_interface.go b/cmd/mocks/flag_set_interface.go index 117a4e4d..1260493d 100644 --- a/cmd/mocks/flag_set_interface.go +++ b/cmd/mocks/flag_set_interface.go @@ -159,6 +159,27 @@ func (_m *FlagSetInterface) GetInt32Wait(flagSet *pflag.FlagSet) (int32, error) return r0, r1 } +// GetInt64RPCTimeout provides a mock function with given fields: flagSet +func (_m *FlagSetInterface) GetInt64RPCTimeout(flagSet *pflag.FlagSet) (int64, error) { + ret := _m.Called(flagSet) + + var r0 int64 + if rf, ok := ret.Get(0).(func(*pflag.FlagSet) int64); ok { + r0 = rf(flagSet) + } else { + r0 = ret.Get(0).(int64) + } + + var r1 error + if rf, ok := ret.Get(1).(func(*pflag.FlagSet) error); ok { + r1 = rf(flagSet) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetInt8Power provides a mock function with given fields: flagSet func (_m *FlagSetInterface) GetInt8Power(flagSet *pflag.FlagSet) (int8, error) { ret := _m.Called(flagSet) @@ -285,6 +306,27 @@ func (_m *FlagSetInterface) GetRootInt32Wait() (int32, error) { return r0, r1 } +// GetRootInt64RPCTimeout provides a mock function with given fields: +func (_m *FlagSetInterface) GetRootInt64RPCTimeout() (int64, error) { + ret := _m.Called() + + var r0 int64 + if rf, ok := ret.Get(0).(func() int64); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(int64) + } + + var r1 error + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetRootStringLogLevel provides a mock function with given fields: func (_m *FlagSetInterface) GetRootStringLogLevel() (string, error) { ret := _m.Called() @@ -516,6 +558,29 @@ func (_m *FlagSetInterface) GetStringSelector(flagSet *pflag.FlagSet) (string, e return r0, r1 } +// GetStringSliceBackupNode provides a mock function with given fields: flagSet +func (_m *FlagSetInterface) GetStringSliceBackupNode(flagSet *pflag.FlagSet) ([]string, error) { + ret := _m.Called(flagSet) + + var r0 []string + if rf, ok := ret.Get(0).(func(*pflag.FlagSet) []string); ok { + r0 = rf(flagSet) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]string) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*pflag.FlagSet) error); ok { + r1 = rf(flagSet) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetStringSliceRogueMode provides a mock function with given fields: flagSet func (_m *FlagSetInterface) GetStringSliceRogueMode(flagSet *pflag.FlagSet) ([]string, error) { ret := _m.Called(flagSet) diff --git a/cmd/mocks/utils_cmd_interface.go b/cmd/mocks/utils_cmd_interface.go index b6a26deb..21a44d96 100644 --- a/cmd/mocks/utils_cmd_interface.go +++ b/cmd/mocks/utils_cmd_interface.go @@ -176,6 +176,11 @@ func (_m *UtilsCmdInterface) CheckDisputeForIds(client *ethclient.Client, transa return r0, r1 } +// CheckToDoResetDispute provides a mock function with given fields: client, blockManager, txnOpts, epoch, sortedValues +func (_m *UtilsCmdInterface) CheckToDoResetDispute(client *ethclient.Client, blockManager *bindings.BlockManager, txnOpts *bind.TransactOpts, epoch uint32, sortedValues []*big.Int) { + _m.Called(client, blockManager, txnOpts, epoch, sortedValues) +} + // ClaimBlockReward provides a mock function with given fields: options func (_m *UtilsCmdInterface) ClaimBlockReward(options types.TransactionOptions) (common.Hash, error) { ret := _m.Called(options) @@ -709,66 +714,25 @@ func (_m *UtilsCmdInterface) GetJobList(client *ethclient.Client) error { return r0 } -// GetLastProposedEpoch provides a mock function with given fields: client, blockNumber, stakerId -func (_m *UtilsCmdInterface) GetLastProposedEpoch(client *ethclient.Client, blockNumber *big.Int, stakerId uint32) (uint32, error) { - ret := _m.Called(client, blockNumber, stakerId) - - var r0 uint32 - if rf, ok := ret.Get(0).(func(*ethclient.Client, *big.Int, uint32) uint32); ok { - r0 = rf(client, blockNumber, stakerId) - } else { - r0 = ret.Get(0).(uint32) - } - - var r1 error - if rf, ok := ret.Get(1).(func(*ethclient.Client, *big.Int, uint32) error); ok { - r1 = rf(client, blockNumber, stakerId) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // GetLocalMediansData provides a mock function with given fields: client, account, epoch, blockNumber, rogueData -func (_m *UtilsCmdInterface) GetLocalMediansData(client *ethclient.Client, account types.Account, epoch uint32, blockNumber *big.Int, rogueData types.Rogue) ([]*big.Int, []uint16, *types.RevealedDataMaps, error) { +func (_m *UtilsCmdInterface) GetLocalMediansData(client *ethclient.Client, account types.Account, epoch uint32, blockNumber *big.Int, rogueData types.Rogue) (types.ProposeFileData, error) { ret := _m.Called(client, account, epoch, blockNumber, rogueData) - var r0 []*big.Int - if rf, ok := ret.Get(0).(func(*ethclient.Client, types.Account, uint32, *big.Int, types.Rogue) []*big.Int); ok { + var r0 types.ProposeFileData + if rf, ok := ret.Get(0).(func(*ethclient.Client, types.Account, uint32, *big.Int, types.Rogue) types.ProposeFileData); ok { r0 = rf(client, account, epoch, blockNumber, rogueData) } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]*big.Int) - } + r0 = ret.Get(0).(types.ProposeFileData) } - var r1 []uint16 - if rf, ok := ret.Get(1).(func(*ethclient.Client, types.Account, uint32, *big.Int, types.Rogue) []uint16); ok { + var r1 error + if rf, ok := ret.Get(1).(func(*ethclient.Client, types.Account, uint32, *big.Int, types.Rogue) error); ok { r1 = rf(client, account, epoch, blockNumber, rogueData) } else { - if ret.Get(1) != nil { - r1 = ret.Get(1).([]uint16) - } - } - - var r2 *types.RevealedDataMaps - if rf, ok := ret.Get(2).(func(*ethclient.Client, types.Account, uint32, *big.Int, types.Rogue) *types.RevealedDataMaps); ok { - r2 = rf(client, account, epoch, blockNumber, rogueData) - } else { - if ret.Get(2) != nil { - r2 = ret.Get(2).(*types.RevealedDataMaps) - } - } - - var r3 error - if rf, ok := ret.Get(3).(func(*ethclient.Client, types.Account, uint32, *big.Int, types.Rogue) error); ok { - r3 = rf(client, account, epoch, blockNumber, rogueData) - } else { - r3 = ret.Error(3) + r1 = ret.Error(1) } - return r0, r1, r2, r3 + return r0, r1 } // GetLogLevel provides a mock function with given fields: @@ -834,6 +798,27 @@ func (_m *UtilsCmdInterface) GetProvider() (string, error) { return r0, r1 } +// GetRPCTimeout provides a mock function with given fields: +func (_m *UtilsCmdInterface) GetRPCTimeout() (int64, error) { + ret := _m.Called() + + var r0 int64 + if rf, ok := ret.Get(0).(func() int64); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(int64) + } + + var r1 error + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetSalt provides a mock function with given fields: client, epoch func (_m *UtilsCmdInterface) GetSalt(client *ethclient.Client, epoch uint32) ([32]byte, error) { ret := _m.Called(client, epoch) @@ -945,14 +930,23 @@ func (_m *UtilsCmdInterface) GetWaitTime() (int32, error) { return r0, r1 } -// GiveSorted provides a mock function with given fields: client, blockManager, txnOpts, epoch, assetId, sortedStakers -func (_m *UtilsCmdInterface) GiveSorted(client *ethclient.Client, blockManager *bindings.BlockManager, txnOpts *bind.TransactOpts, epoch uint32, assetId uint16, sortedStakers []*big.Int) { - _m.Called(client, blockManager, txnOpts, epoch, assetId, sortedStakers) +// GiveSorted provides a mock function with given fields: client, blockManager, txnArgs, epoch, assetId, sortedStakers +func (_m *UtilsCmdInterface) GiveSorted(client *ethclient.Client, blockManager *bindings.BlockManager, txnArgs types.TransactionOptions, epoch uint32, assetId uint16, sortedStakers []*big.Int) error { + ret := _m.Called(client, blockManager, txnArgs, epoch, assetId, sortedStakers) + + var r0 error + if rf, ok := ret.Get(0).(func(*ethclient.Client, *bindings.BlockManager, types.TransactionOptions, uint32, uint16, []*big.Int) error); ok { + r0 = rf(client, blockManager, txnArgs, epoch, assetId, sortedStakers) + } else { + r0 = ret.Error(0) + } + + return r0 } -// HandleBlock provides a mock function with given fields: client, account, blockNumber, config, rogueData -func (_m *UtilsCmdInterface) HandleBlock(client *ethclient.Client, account types.Account, blockNumber *big.Int, config types.Configurations, rogueData types.Rogue) { - _m.Called(client, account, blockNumber, config, rogueData) +// HandleBlock provides a mock function with given fields: client, account, blockNumber, config, rogueData, backupNodeActionsToIgnore +func (_m *UtilsCmdInterface) HandleBlock(client *ethclient.Client, account types.Account, blockNumber *big.Int, config types.Configurations, rogueData types.Rogue, backupNodeActionsToIgnore []string) { + _m.Called(client, account, blockNumber, config, rogueData, backupNodeActionsToIgnore) } // HandleClaimBounty provides a mock function with given fields: client, config, account @@ -990,13 +984,13 @@ func (_m *UtilsCmdInterface) HandleCommitState(client *ethclient.Client, epoch u return r0, r1 } -// HandleDispute provides a mock function with given fields: client, config, account, epoch, blockNumber, rogueData -func (_m *UtilsCmdInterface) HandleDispute(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, blockNumber *big.Int, rogueData types.Rogue) error { - ret := _m.Called(client, config, account, epoch, blockNumber, rogueData) +// HandleDispute provides a mock function with given fields: client, config, account, epoch, blockNumber, rogueData, backupNodeActionsToIgnore +func (_m *UtilsCmdInterface) HandleDispute(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, blockNumber *big.Int, rogueData types.Rogue, backupNodeActionsToIgnore []string) error { + ret := _m.Called(client, config, account, epoch, blockNumber, rogueData, backupNodeActionsToIgnore) var r0 error - if rf, ok := ret.Get(0).(func(*ethclient.Client, types.Configurations, types.Account, uint32, *big.Int, types.Rogue) error); ok { - r0 = rf(client, config, account, epoch, blockNumber, rogueData) + if rf, ok := ret.Get(0).(func(*ethclient.Client, types.Configurations, types.Account, uint32, *big.Int, types.Rogue, []string) error); ok { + r0 = rf(client, config, account, epoch, blockNumber, rogueData, backupNodeActionsToIgnore) } else { r0 = ret.Error(0) } @@ -1296,26 +1290,17 @@ func (_m *UtilsCmdInterface) ModifyCollectionStatus(client *ethclient.Client, co } // Propose provides a mock function with given fields: client, config, account, staker, epoch, blockNumber, rogueData -func (_m *UtilsCmdInterface) Propose(client *ethclient.Client, config types.Configurations, account types.Account, staker bindings.StructsStaker, epoch uint32, blockNumber *big.Int, rogueData types.Rogue) (common.Hash, error) { +func (_m *UtilsCmdInterface) Propose(client *ethclient.Client, config types.Configurations, account types.Account, staker bindings.StructsStaker, epoch uint32, blockNumber *big.Int, rogueData types.Rogue) error { ret := _m.Called(client, config, account, staker, epoch, blockNumber, rogueData) - var r0 common.Hash - if rf, ok := ret.Get(0).(func(*ethclient.Client, types.Configurations, types.Account, bindings.StructsStaker, uint32, *big.Int, types.Rogue) common.Hash); ok { + var r0 error + if rf, ok := ret.Get(0).(func(*ethclient.Client, types.Configurations, types.Account, bindings.StructsStaker, uint32, *big.Int, types.Rogue) error); ok { r0 = rf(client, config, account, staker, epoch, blockNumber, rogueData) } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(common.Hash) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(*ethclient.Client, types.Configurations, types.Account, bindings.StructsStaker, uint32, *big.Int, types.Rogue) error); ok { - r1 = rf(client, config, account, staker, epoch, blockNumber, rogueData) - } else { - r1 = ret.Error(1) + r0 = ret.Error(0) } - return r0, r1 + return r0 } // ResetDispute provides a mock function with given fields: client, blockManager, txnOpts, epoch @@ -1572,13 +1557,13 @@ func (_m *UtilsCmdInterface) UpdateJob(client *ethclient.Client, config types.Co return r0, r1 } -// Vote provides a mock function with given fields: ctx, config, client, rogueData, account -func (_m *UtilsCmdInterface) Vote(ctx context.Context, config types.Configurations, client *ethclient.Client, rogueData types.Rogue, account types.Account) error { - ret := _m.Called(ctx, config, client, rogueData, account) +// Vote provides a mock function with given fields: ctx, config, client, rogueData, account, backupNodeActionsToIgnore +func (_m *UtilsCmdInterface) Vote(ctx context.Context, config types.Configurations, client *ethclient.Client, rogueData types.Rogue, account types.Account, backupNodeActionsToIgnore []string) error { + ret := _m.Called(ctx, config, client, rogueData, account, backupNodeActionsToIgnore) var r0 error - if rf, ok := ret.Get(0).(func(context.Context, types.Configurations, *ethclient.Client, types.Rogue, types.Account) error); ok { - r0 = rf(ctx, config, client, rogueData, account) + if rf, ok := ret.Get(0).(func(context.Context, types.Configurations, *ethclient.Client, types.Rogue, types.Account, []string) error); ok { + r0 = rf(ctx, config, client, rogueData, account, backupNodeActionsToIgnore) } else { r0 = ret.Error(0) } diff --git a/cmd/mocks/utils_interface.go b/cmd/mocks/utils_interface.go index fed07d8b..babe15ad 100644 --- a/cmd/mocks/utils_interface.go +++ b/cmd/mocks/utils_interface.go @@ -57,13 +57,13 @@ func (_m *UtilsInterface) AssignLogFile(flagSet *pflag.FlagSet) { _m.Called(flagSet) } -// AssignPassword provides a mock function with given fields: -func (_m *UtilsInterface) AssignPassword() string { - ret := _m.Called() +// AssignPassword provides a mock function with given fields: flagSet +func (_m *UtilsInterface) AssignPassword(flagSet *pflag.FlagSet) string { + ret := _m.Called(flagSet) var r0 string - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(*pflag.FlagSet) string); ok { + r0 = rf(flagSet) } else { r0 = ret.Get(0).(string) } @@ -561,6 +561,27 @@ func (_m *UtilsInterface) GetEpochLastCommitted(client *ethclient.Client, staker return r0, r1 } +// GetEpochLastProposed provides a mock function with given fields: client, stakerId +func (_m *UtilsInterface) GetEpochLastProposed(client *ethclient.Client, stakerId uint32) (uint32, error) { + ret := _m.Called(client, stakerId) + + var r0 uint32 + if rf, ok := ret.Get(0).(func(*ethclient.Client, uint32) uint32); ok { + r0 = rf(client, stakerId) + } else { + r0 = ret.Get(0).(uint32) + } + + var r1 error + if rf, ok := ret.Get(1).(func(*ethclient.Client, uint32) error); ok { + r1 = rf(client, stakerId) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetEpochLastRevealed provides a mock function with given fields: client, stakerId func (_m *UtilsInterface) GetEpochLastRevealed(client *ethclient.Client, stakerId uint32) (uint32, error) { ret := _m.Called(client, stakerId) @@ -1311,13 +1332,13 @@ func (_m *UtilsInterface) SaveDataToDisputeJsonFile(filePath string, bountyIdQue return r0 } -// SaveDataToProposeJsonFile provides a mock function with given fields: flePath, epoch, proposeFileData -func (_m *UtilsInterface) SaveDataToProposeJsonFile(flePath string, epoch uint32, proposeFileData types.ProposeData) error { - ret := _m.Called(flePath, epoch, proposeFileData) +// SaveDataToProposeJsonFile provides a mock function with given fields: flePath, proposeFileData +func (_m *UtilsInterface) SaveDataToProposeJsonFile(flePath string, proposeFileData types.ProposeFileData) error { + ret := _m.Called(flePath, proposeFileData) var r0 error - if rf, ok := ret.Get(0).(func(string, uint32, types.ProposeData) error); ok { - r0 = rf(flePath, epoch, proposeFileData) + if rf, ok := ret.Get(0).(func(string, types.ProposeFileData) error); ok { + r0 = rf(flePath, proposeFileData) } else { r0 = ret.Error(0) } diff --git a/cmd/modifyCollectionStatus.go b/cmd/modifyCollectionStatus.go index 8aaa9a41..3eb0b3f1 100644 --- a/cmd/modifyCollectionStatus.go +++ b/cmd/modifyCollectionStatus.go @@ -32,16 +32,20 @@ func initialiseModifyCollectionStatus(cmd *cobra.Command, args []string) { func (*UtilsStruct) ExecuteModifyCollectionStatus(flagSet *pflag.FlagSet) { config, err := cmdUtils.GetConfigData() utils.CheckError("Error in getting config: ", err) + log.Debugf("ExecuteModifyCollectionStatus: Config: %+v: ", config) client := razorUtils.ConnectToClient(config.Provider) address, err := flagSetUtils.GetStringAddress(flagSet) utils.CheckError("Error in getting address: ", err) + log.Debug("ExecuteModifyCollectionStatus: Address: ", address) logger.SetLoggerParameters(client, address) + log.Debug("Checking to assign log file...") razorUtils.AssignLogFile(flagSet) - password := razorUtils.AssignPassword() + log.Debug("Getting password...") + password := razorUtils.AssignPassword(flagSet) collectionId, err := flagSetUtils.GetUint16CollectionId(flagSet) utils.CheckError("Error in getting collectionId: ", err) @@ -58,6 +62,7 @@ func (*UtilsStruct) ExecuteModifyCollectionStatus(flagSet *pflag.FlagSet) { CollectionId: collectionId, } + log.Debugf("Calling ModifyCollectionStatus() with arguments modifyCollectionInput = %+v", modifyCollectionInput) txn, err := cmdUtils.ModifyCollectionStatus(client, config, modifyCollectionInput) utils.CheckError("Error in changing collection active status: ", err) if txn != core.NilHash { @@ -79,6 +84,7 @@ func (*UtilsStruct) ModifyCollectionStatus(client *ethclient.Client, config type log.Error("Error in fetching active status") return core.NilHash, err } + log.Debug("ModifyCollectionStatus: Current status of collection: ", currentStatus) if currentStatus == modifyCollectionInput.Status { log.Errorf("Collection %d has the active status already set to %t", modifyCollectionInput.CollectionId, modifyCollectionInput.Status) return core.NilHash, nil @@ -102,6 +108,7 @@ func (*UtilsStruct) ModifyCollectionStatus(client *ethclient.Client, config type txnOpts := razorUtils.GetTxnOpts(txnArgs) log.Infof("Changing active status of collection: %d from %t to %t", modifyCollectionInput.CollectionId, !modifyCollectionInput.Status, modifyCollectionInput.Status) + log.Debugf("Executing SetCollectionStatus transaction with status = %v, collectionId = %d", modifyCollectionInput.Status, modifyCollectionInput.CollectionId) txn, err := assetManagerUtils.SetCollectionStatus(client, txnOpts, modifyCollectionInput.Status, modifyCollectionInput.CollectionId) if err != nil { return core.NilHash, err @@ -116,11 +123,13 @@ func init() { Address string CollectionId uint16 Status string + Password string ) modifyCollectionStatusCmd.Flags().StringVarP(&Address, "address", "a", "", "address of the user") modifyCollectionStatusCmd.Flags().Uint16VarP(&CollectionId, "collectionId", "", 0, "collectionId of the collection") modifyCollectionStatusCmd.Flags().StringVarP(&Status, "status", "", "true", "active status of the collection") + modifyCollectionStatusCmd.Flags().StringVarP(&Password, "password", "", "", "password path of user to protect the keystore") addressErr := modifyCollectionStatusCmd.MarkFlagRequired("address") utils.CheckError("Address error: ", addressErr) diff --git a/cmd/modifyCollectionStatus_test.go b/cmd/modifyCollectionStatus_test.go index 7e2a253e..bf473e9f 100644 --- a/cmd/modifyCollectionStatus_test.go +++ b/cmd/modifyCollectionStatus_test.go @@ -357,7 +357,7 @@ func TestExecuteModifyAssetStatus(t *testing.T) { flagsetUtilsMock.On("GetStringAddress", flagSet).Return(tt.args.address, tt.args.addressErr) flagsetUtilsMock.On("GetUint16CollectionId", flagSet).Return(tt.args.collectionId, tt.args.collectionIdErr) flagsetUtilsMock.On("GetStringStatus", flagSet).Return(tt.args.status, tt.args.statusErr) - utilsMock.On("AssignPassword").Return(tt.args.password) + utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) stringMock.On("ParseBool", mock.AnythingOfType("string")).Return(tt.args.parseStatus, tt.args.parseStatusErr) utilsMock.On("ConnectToClient", mock.AnythingOfType("string")).Return(client) cmdUtilsMock.On("ModifyCollectionStatus", mock.Anything, mock.Anything, mock.Anything).Return(tt.args.ModifyCollectionStatusHash, tt.args.ModifyCollectionStatusErr) diff --git a/cmd/propose.go b/cmd/propose.go index ba606b91..311098c0 100644 --- a/cmd/propose.go +++ b/cmd/propose.go @@ -4,7 +4,6 @@ package cmd import ( "encoding/hex" "errors" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" solsha3 "github.com/miguelmota/go-solidity-sha3" "math" @@ -17,11 +16,7 @@ import ( "time" ) -var ( - _mediansData []*big.Int - _revealedCollectionIds []uint16 - _revealedDataMaps *types.RevealedDataMaps -) +var globalProposedDataStruct types.ProposeFileData // Index reveal events of staker's // Reveal Event would have two things, activeCollectionIndex/medianIndex and values @@ -32,17 +27,18 @@ var ( // Find iteration using salt as seed //This functions handles the propose state -func (*UtilsStruct) Propose(client *ethclient.Client, config types.Configurations, account types.Account, staker bindings.StructsStaker, epoch uint32, blockNumber *big.Int, rogueData types.Rogue) (common.Hash, error) { +func (*UtilsStruct) Propose(client *ethclient.Client, config types.Configurations, account types.Account, staker bindings.StructsStaker, epoch uint32, blockNumber *big.Int, rogueData types.Rogue) error { if state, err := razorUtils.GetDelayedState(client, config.BufferPercent); err != nil || state != 2 { log.Error("Not propose state") - return core.NilHash, err + return err } numStakers, err := razorUtils.GetNumberOfStakers(client) if err != nil { log.Error("Error in fetching number of stakers: ", err) - return core.NilHash, err + return err } - log.Debug("Stake: ", staker.Stake) + log.Debug("Propose: Number of stakers: ", numStakers) + log.Debug("Propose: Stake: ", staker.Stake) var ( biggestStake *big.Int @@ -51,104 +47,98 @@ func (*UtilsStruct) Propose(client *ethclient.Client, config types.Configuration ) if rogueData.IsRogue && utils.Contains(rogueData.RogueMode, "biggestStakerId") { + log.Warn("YOU ARE PROPOSING IN ROGUE MODE, THIS CAN INCUR PENALTIES!") // If staker is going rogue with biggestStakerId than we do biggestStakerId = smallestStakerId smallestStake, smallestStakerId, smallestStakerErr := cmdUtils.GetSmallestStakeAndId(client, epoch) if smallestStakerErr != nil { log.Error("Error in calculating smallest staker: ", smallestStakerErr) - return core.NilHash, smallestStakerErr + return smallestStakerErr } biggestStake = smallestStake biggestStakerId = smallestStakerId + log.Debugf("Propose: In rogue mode, Biggest Stake: %s, Biggest Staker Id: %d", biggestStake, biggestStakerId) } else { biggestStake, biggestStakerId, biggestStakerErr = cmdUtils.GetBiggestStakeAndId(client, account.Address, epoch) if biggestStakerErr != nil { log.Error("Error in calculating biggest staker: ", biggestStakerErr) - return core.NilHash, biggestStakerErr + return biggestStakerErr } } + log.Debugf("Getting Salt for current epoch %d...", epoch) salt, err := cmdUtils.GetSalt(client, epoch) if err != nil { - return core.NilHash, err + return err } log.Debugf("Biggest staker Id: %d Biggest stake: %s, Stake: %s, Staker Id: %d, Number of Stakers: %d, Salt: %s", biggestStakerId, biggestStake, staker.Stake, staker.Id, numStakers, hex.EncodeToString(salt[:])) bufferPercent, err := cmdUtils.GetBufferPercent() if err != nil { - return core.NilHash, err + return err } - iteration := cmdUtils.GetIteration(client, types.ElectedProposer{ + proposer := types.ElectedProposer{ Stake: staker.Stake, StakerId: staker.Id, BiggestStake: biggestStake, NumberOfStakers: numStakers, Salt: salt, Epoch: epoch, - }, bufferPercent) + } + log.Debugf("Propose: Calling GetIteration with arguments proposer = %+v, buffer percent = %d", proposer, bufferPercent) + iteration := cmdUtils.GetIteration(client, proposer, bufferPercent) log.Debug("Iteration: ", iteration) if iteration == -1 { - return core.NilHash, nil + return nil } numOfProposedBlocks, err := razorUtils.GetNumberOfProposedBlocks(client, epoch) if err != nil { log.Error(err) - return core.NilHash, err + return err } + log.Debug("Propose: Number of proposed blocks: ", numOfProposedBlocks) maxAltBlocks, err := razorUtils.GetMaxAltBlocks(client) if err != nil { log.Error(err) - return core.NilHash, err + return err } + log.Debug("Propose: Number of maximum alternative blocks: ", maxAltBlocks) if numOfProposedBlocks >= maxAltBlocks { log.Debugf("Number of blocks proposed: %d, which is equal or greater than maximum alternative blocks allowed", numOfProposedBlocks) log.Debug("Comparing iterations...") - lastBlockIndex := numOfProposedBlocks - 1 - lastProposedBlockStruct, err := razorUtils.GetProposedBlock(client, epoch, uint32(lastBlockIndex)) + sortedProposedBlocks, err := razorUtils.GetSortedProposedBlockIds(client, epoch) + if err != nil { + log.Error("Error in fetching sorted proposed block ids") + return err + } + log.Debug("Propose: Sorted proposed blocks: ", sortedProposedBlocks) + lastBlockIndex := sortedProposedBlocks[numOfProposedBlocks-1] + log.Debug("Propose: Last block index: ", lastBlockIndex) + lastProposedBlockStruct, err := razorUtils.GetProposedBlock(client, epoch, lastBlockIndex) if err != nil { log.Error(err) - return core.NilHash, err + return err } + log.Debugf("Propose: Last proposed block: %+v", lastProposedBlockStruct) lastIteration := lastProposedBlockStruct.Iteration + log.Debug("Propose: Iteration of last proposed block: ", lastIteration) if lastIteration.Cmp(big.NewInt(int64(iteration))) < 0 { log.Info("Current iteration is greater than iteration of last proposed block, cannot propose") - return core.NilHash, nil + return nil } log.Info("Current iteration is less than iteration of last proposed block, can propose") } + log.Debugf("Propose: Calling MakeBlock() with arguments blockNumber = %s, epoch = %d, rogueData = %+v", blockNumber, epoch, rogueData) medians, ids, revealedDataMaps, err := cmdUtils.MakeBlock(client, blockNumber, epoch, rogueData) if err != nil { log.Error(err) - return core.NilHash, err - } - - _mediansData = medians - _revealedCollectionIds = ids - _revealedDataMaps = revealedDataMaps - - log.Debug("Saving proposed data for recovery") - fileName, err := razorUtils.GetProposeDataFileName(account.Address) - if err != nil { - log.Error("Error in getting file name to save median data: ", err) - return core.NilHash, nil - } - err = razorUtils.SaveDataToProposeJsonFile(fileName, epoch, types.ProposeData{ - MediansData: _mediansData, - RevealedCollectionIds: _revealedCollectionIds, - RevealedDataMaps: _revealedDataMaps, - }) - if err != nil { - log.Errorf("Error in saving data to file %s: %t", fileName, err) - return core.NilHash, nil + return err } - log.Debug("Data saved!") - - log.Debugf("Medians: %d", medians) - - log.Debugf("Epoch: %d Medians: %d", epoch, medians) - log.Debugf("Iteration: %d Biggest Staker Id: %d", iteration, biggestStakerId) + log.Debugf("Propose: Medians: %d", medians) + log.Debugf("Propose: Epoch: %d Medians: %d", epoch, medians) + log.Debugf("Propose: Iteration: %d Biggest Staker Id: %d", iteration, biggestStakerId) log.Info("Proposing block...") txnOpts := razorUtils.GetTxnOpts(types.TransactionOptions{ @@ -163,13 +153,47 @@ func (*UtilsStruct) Propose(client *ethclient.Client, config types.Configuration Parameters: []interface{}{epoch, ids, medians, big.NewInt(int64(iteration)), biggestStakerId}, }) + log.Debugf("Executing Propose transaction with epoch = %d, Ids = %v, medians = %s, iteration = %s, biggestStakerId = %d", epoch, ids, medians, big.NewInt(int64(iteration)), biggestStakerId) txn, err := blockManagerUtils.Propose(client, txnOpts, epoch, ids, medians, big.NewInt(int64(iteration)), biggestStakerId) if err != nil { log.Error(err) - return core.NilHash, err + return err + } + proposeTxn := transactionUtils.Hash(txn) + log.Info("Txn Hash: ", proposeTxn) + if proposeTxn != core.NilHash { + waitForBlockCompletionErr := razorUtils.WaitForBlockCompletion(client, proposeTxn.String()) + if waitForBlockCompletionErr != nil { + log.Error("Error in WaitForBlockCompletionErr for propose: ", waitForBlockCompletionErr) + return waitForBlockCompletionErr + } else { + // Saving proposed data after successful propose + log.Debug("Updating global propose data struct...") + updateGlobalProposedDataStruct(types.ProposeFileData{ + MediansData: medians, + RevealedDataMaps: revealedDataMaps, + RevealedCollectionIds: ids, + Epoch: epoch, + }) + log.Debugf("Propose: Global propose data struct: %+v", globalProposedDataStruct) + + log.Debug("Saving proposed data for recovery...") + fileName, err := razorUtils.GetProposeDataFileName(account.Address) + if err != nil { + log.Error("Error in getting file name to save median data: ", err) + return err + } + log.Debug("Propose: Propose data file path: ", fileName) + err = razorUtils.SaveDataToProposeJsonFile(fileName, globalProposedDataStruct) + if err != nil { + log.Errorf("Error in saving data to file %s: %v", fileName, err) + return err + } + log.Debug("Data saved!") + } } - log.Info("Txn Hash: ", transactionUtils.Hash(txn)) - return transactionUtils.Hash(txn), nil + + return nil } //This function returns the biggest stake and Id of it @@ -178,6 +202,7 @@ func (*UtilsStruct) GetBiggestStakeAndId(client *ethclient.Client, address strin if err != nil { return nil, 0, err } + log.Debug("GetBiggestStakeAndId: Number of Stakers: ", numberOfStakers) if numberOfStakers == 0 { return nil, 0, errors.New("numberOfStakers is 0") } @@ -188,13 +213,16 @@ func (*UtilsStruct) GetBiggestStakeAndId(client *ethclient.Client, address strin if err != nil { return nil, 0, err } + log.Debug("GetBiggestStakeAndId: Buffer Percent: ", bufferPercent) stateRemainingTime, err := utilsInterface.GetRemainingTimeOfCurrentState(client, bufferPercent) if err != nil { return nil, 0, err } + log.Debug("GetBiggestStakeAndId: State remaining time: ", stateRemainingTime) stateTimeout := time.NewTimer(time.Second * time.Duration(stateRemainingTime)) + log.Debug("Iterating over all the stakers...") loop: for i := 1; i <= int(numberOfStakers); i++ { select { @@ -203,10 +231,12 @@ loop: err = errors.New("state timeout error") break loop default: + log.Debug("Propose: Staker Id: ", i) stake, err := razorUtils.GetStakeSnapshot(client, uint32(i), epoch) if err != nil { return nil, 0, err } + log.Debugf("Stake Snapshot of staker having stakerId %d is %s", i, stake) if stake.Cmp(biggestStake) > 0 { biggestStake = stake biggestStakerId = uint32(i) @@ -216,6 +246,8 @@ loop: if err != nil { return nil, 0, err } + log.Debug("Propose: BiggestStake: ", biggestStake) + log.Debug("Propose: Biggest Staker Id: ", biggestStakerId) return biggestStake, biggestStakerId, nil } @@ -226,12 +258,16 @@ func (*UtilsStruct) GetIteration(client *ethclient.Client, proposer types.Electe log.Error("Error in fetching influence of staker: ", err) return -1 } + log.Debug("GetIteration: Stake: ", stake) currentStakerStake := big.NewInt(1).Mul(stake, big.NewInt(int64(math.Exp2(32)))) stateRemainingTime, err := utilsInterface.GetRemainingTimeOfCurrentState(client, bufferPercent) if err != nil { return -1 } stateTimeout := time.NewTimer(time.Second * time.Duration(stateRemainingTime)) + log.Debug("GetIteration: State remaining time: ", stateRemainingTime) + log.Debug("Calculating Iteration...") + log.Debugf("GetIteration: Calling IsElectedProposer() to find iteration...") loop: for i := 0; i < 10000000; i++ { select { @@ -252,6 +288,7 @@ loop: //This function returns if the elected staker is proposer or not func (*UtilsStruct) IsElectedProposer(proposer types.ElectedProposer, currentStakerStake *big.Int) bool { seed := solsha3.SoliditySHA3([]string{"uint256"}, []interface{}{big.NewInt(int64(proposer.Iteration))}) + pseudoRandomNumber := pseudoRandomNumberGenerator(seed, proposer.NumberOfStakers, proposer.Salt[:]) //add +1 since prng returns 0 to max-1 and staker start from 1 pseudoRandomNumber = pseudoRandomNumber.Add(pseudoRandomNumber, big.NewInt(1)) @@ -259,11 +296,18 @@ func (*UtilsStruct) IsElectedProposer(proposer types.ElectedProposer, currentSta return false } seed2 := solsha3.SoliditySHA3([]string{"uint256", "uint256"}, []interface{}{big.NewInt(int64(proposer.StakerId)), big.NewInt(int64(proposer.Iteration))}) + log.Debug("IsElectedProposer: Seed: ", seed) + log.Debug("IsElectedProposer: Pseudo random number: ", pseudoRandomNumber) + log.Debug("IsElectedProposer: Seed 2: ", seed2) randomHash := solsha3.SoliditySHA3([]string{"bytes32", "bytes32"}, []interface{}{"0x" + hex.EncodeToString(proposer.Salt[:]), "0x" + hex.EncodeToString(seed2)}) randomHashNumber := big.NewInt(0).SetBytes(randomHash) randomHashNumber = randomHashNumber.Mod(randomHashNumber, big.NewInt(int64(math.Exp2(32)))) + log.Debug("IsElectedProposer: Random hash number: ", randomHashNumber) biggestStake := big.NewInt(1).Mul(randomHashNumber, proposer.BiggestStake) - return biggestStake.Cmp(currentStakerStake) <= 0 + log.Debug("IsElectedProposer: Biggest stake: ", biggestStake) + isElected := biggestStake.Cmp(currentStakerStake) <= 0 + log.Debug("IsElectedProposer: Is staker elected: ", isElected) + return isElected } //This function returns the pseudo random number @@ -275,13 +319,16 @@ func pseudoRandomNumberGenerator(seed []byte, max uint32, blockHashes []byte) *b //This function returns the sorted revealed values func (*UtilsStruct) GetSortedRevealedValues(client *ethclient.Client, blockNumber *big.Int, epoch uint32) (*types.RevealedDataMaps, error) { + log.Debugf("GetSortedRevealedValues: Calling IndexRevealEventsOfCurrentEpoch with arguments blockNumber = %s, epoch = %d", blockNumber, epoch) assignedAsset, err := cmdUtils.IndexRevealEventsOfCurrentEpoch(client, blockNumber, epoch) if err != nil { return nil, err } + log.Debugf("GetSortedRevealedValues: Revealed Data: %+v", assignedAsset) revealedValuesWithIndex := make(map[uint16][]*big.Int) voteWeights := make(map[string]*big.Int) influenceSum := make(map[uint16]*big.Int) + log.Debug("Calculating sorted revealed values, vote weights and influence sum...") for _, asset := range assignedAsset { for _, assetValue := range asset.RevealedValues { if revealedValuesWithIndex[assetValue.LeafId] == nil { @@ -319,21 +366,25 @@ func (*UtilsStruct) GetSortedRevealedValues(client *ethclient.Client, blockNumbe //This function returns the medians, idsRevealedInThisEpoch and revealedDataMaps func (*UtilsStruct) MakeBlock(client *ethclient.Client, blockNumber *big.Int, epoch uint32, rogueData types.Rogue) ([]*big.Int, []uint16, *types.RevealedDataMaps, error) { + log.Debugf("MakeBlock: Calling GetSortedRevealedValues with arguments blockNumber = %s, epoch = %d", blockNumber, epoch) revealedDataMaps, err := cmdUtils.GetSortedRevealedValues(client, blockNumber, epoch) if err != nil { return nil, nil, nil, err } + log.Debugf("MakeBlock: Revealed data map: %+v", revealedDataMaps) activeCollections, err := razorUtils.GetActiveCollections(client) if err != nil { return nil, nil, nil, err } + log.Debug("MakeBlock: Active collections: ", activeCollections) var ( medians []*big.Int idsRevealedInThisEpoch []uint16 ) + log.Debug("Iterating over all the active collections for medians calculation....") for leafId := uint16(0); leafId < uint16(len(activeCollections)); leafId++ { influenceSum := revealedDataMaps.InfluenceSum[leafId] if influenceSum != nil && influenceSum.Cmp(big.NewInt(0)) != 0 { @@ -354,15 +405,18 @@ func (*UtilsStruct) MakeBlock(client *ethclient.Client, blockNumber *big.Int, ep } } if rogueData.IsRogue && utils.Contains(rogueData.RogueMode, "missingIds") { + log.Warn("YOU ARE PROPOSING IDS REVEALED IN ROGUE MODE, THIS CAN INCUR PENALTIES!") //Replacing the last ID: id with id+1 in idsRevealed array if rogueMode == missingIds idsRevealedInThisEpoch[len(idsRevealedInThisEpoch)-1] = idsRevealedInThisEpoch[len(idsRevealedInThisEpoch)-1] + 1 } if rogueData.IsRogue && utils.Contains(rogueData.RogueMode, "extraIds") { + log.Warn("YOU ARE PROPOSING IDS REVEALED IN ROGUE MODE, THIS CAN INCUR PENALTIES!") //Adding a dummy median and appending extra id to idsRevealed array if rogueMode == extraIds medians = append(medians, razorUtils.GetRogueRandomValue(10000000)) idsRevealedInThisEpoch = append(idsRevealedInThisEpoch, idsRevealedInThisEpoch[len(idsRevealedInThisEpoch)-1]+1) } if rogueData.IsRogue && utils.Contains(rogueData.RogueMode, "unsortedIds") && len(idsRevealedInThisEpoch) > 1 { + log.Warn("YOU ARE PROPOSING IDS REVEALED IN ROGUE MODE, THIS CAN INCUR PENALTIES!") //Interchanging the first 2 elements of idsRevealed array temp := idsRevealedInThisEpoch[0] idsRevealedInThisEpoch[0] = idsRevealedInThisEpoch[1] @@ -407,3 +461,11 @@ func (*UtilsStruct) GetSmallestStakeAndId(client *ethclient.Client, epoch uint32 } return smallestStake, smallestStakerId, nil } + +func updateGlobalProposedDataStruct(proposedData types.ProposeFileData) types.ProposeFileData { + globalProposedDataStruct.MediansData = proposedData.MediansData + globalProposedDataStruct.RevealedDataMaps = proposedData.RevealedDataMaps + globalProposedDataStruct.RevealedCollectionIds = proposedData.RevealedCollectionIds + globalProposedDataStruct.Epoch = proposedData.Epoch + return globalProposedDataStruct +} diff --git a/cmd/propose_test.go b/cmd/propose_test.go index 0afc401b..2d9e44ab 100644 --- a/cmd/propose_test.go +++ b/cmd/propose_test.go @@ -9,7 +9,6 @@ import ( "github.com/stretchr/testify/mock" "math/big" "razor/cmd/mocks" - "razor/core" "razor/core/types" "razor/pkg/bindings" "razor/utils" @@ -63,6 +62,8 @@ func TestPropose(t *testing.T) { iteration int numOfProposedBlocks uint8 numOfProposedBlocksErr error + sortedProposedBlockIds []uint32 + sortedProposedBlocksIdsErr error maxAltBlocks uint8 maxAltBlocksErr error lastIteration *big.Int @@ -80,11 +81,11 @@ func TestPropose(t *testing.T) { proposeTxn *Types.Transaction proposeErr error hash common.Hash + waitForBlockCompletionErr error } tests := []struct { name string args args - want common.Hash wantErr error }{ { @@ -98,6 +99,7 @@ func TestPropose(t *testing.T) { salt: saltBytes32, iteration: 1, numOfProposedBlocks: 3, + sortedProposedBlockIds: []uint32{2, 1, 0}, maxAltBlocks: 4, lastIteration: big.NewInt(5), lastProposedBlockStruct: bindings.StructsBlock{}, @@ -106,7 +108,6 @@ func TestPropose(t *testing.T) { proposeTxn: &Types.Transaction{}, hash: common.BigToHash(big.NewInt(1)), }, - want: common.BigToHash(big.NewInt(1)), wantErr: nil, }, { @@ -120,6 +121,7 @@ func TestPropose(t *testing.T) { salt: saltBytes32, iteration: 1, numOfProposedBlocks: 3, + sortedProposedBlockIds: []uint32{2, 1, 0}, maxAltBlocks: 4, lastIteration: big.NewInt(5), lastProposedBlockStruct: bindings.StructsBlock{}, @@ -128,7 +130,6 @@ func TestPropose(t *testing.T) { proposeTxn: &Types.Transaction{}, hash: common.BigToHash(big.NewInt(1)), }, - want: core.NilHash, wantErr: errors.New("state error"), }, { @@ -142,6 +143,7 @@ func TestPropose(t *testing.T) { salt: saltBytes32, iteration: 1, numOfProposedBlocks: 2, + sortedProposedBlockIds: []uint32{1, 0}, maxAltBlocks: 4, lastIteration: big.NewInt(5), lastProposedBlockStruct: bindings.StructsBlock{}, @@ -150,7 +152,6 @@ func TestPropose(t *testing.T) { proposeTxn: &Types.Transaction{}, hash: common.BigToHash(big.NewInt(1)), }, - want: core.NilHash, wantErr: errors.New("numberOfStakers error"), }, { @@ -163,6 +164,7 @@ func TestPropose(t *testing.T) { salt: saltBytes32, iteration: 1, numOfProposedBlocks: 3, + sortedProposedBlockIds: []uint32{2, 1, 0}, maxAltBlocks: 4, lastIteration: big.NewInt(5), lastProposedBlockStruct: bindings.StructsBlock{}, @@ -171,7 +173,6 @@ func TestPropose(t *testing.T) { proposeTxn: &Types.Transaction{}, hash: common.BigToHash(big.NewInt(1)), }, - want: core.NilHash, wantErr: errors.New("biggest staker error"), }, { @@ -185,6 +186,7 @@ func TestPropose(t *testing.T) { saltErr: errors.New("salt error"), iteration: 1, numOfProposedBlocks: 3, + sortedProposedBlockIds: []uint32{2, 0, 1}, maxAltBlocks: 4, lastIteration: big.NewInt(5), lastProposedBlockStruct: bindings.StructsBlock{}, @@ -193,7 +195,6 @@ func TestPropose(t *testing.T) { proposeTxn: &Types.Transaction{}, hash: common.BigToHash(big.NewInt(1)), }, - want: core.NilHash, wantErr: errors.New("salt error"), }, { @@ -207,6 +208,7 @@ func TestPropose(t *testing.T) { salt: saltBytes32, iteration: -1, numOfProposedBlocks: 3, + sortedProposedBlockIds: []uint32{2, 0, 1}, maxAltBlocks: 4, lastIteration: big.NewInt(5), lastProposedBlockStruct: bindings.StructsBlock{}, @@ -215,7 +217,6 @@ func TestPropose(t *testing.T) { proposeTxn: &Types.Transaction{}, hash: common.BigToHash(big.NewInt(1)), }, - want: core.NilHash, wantErr: nil, }, { @@ -229,6 +230,7 @@ func TestPropose(t *testing.T) { salt: saltBytes32, iteration: 1, numOfProposedBlocksErr: errors.New("numOfProposedBlocks error"), + sortedProposedBlockIds: []uint32{2, 0, 1}, maxAltBlocks: 4, lastIteration: big.NewInt(5), lastProposedBlockStruct: bindings.StructsBlock{}, @@ -237,7 +239,6 @@ func TestPropose(t *testing.T) { proposeTxn: &Types.Transaction{}, hash: common.BigToHash(big.NewInt(1)), }, - want: core.NilHash, wantErr: errors.New("numOfProposedBlocks error"), }, { @@ -251,6 +252,7 @@ func TestPropose(t *testing.T) { salt: saltBytes32, iteration: 1, numOfProposedBlocks: 2, + sortedProposedBlockIds: []uint32{0, 1}, maxAltBlocksErr: errors.New("maxAltBlocks error"), lastIteration: big.NewInt(5), lastProposedBlockStruct: bindings.StructsBlock{}, @@ -259,7 +261,6 @@ func TestPropose(t *testing.T) { proposeTxn: &Types.Transaction{}, hash: common.BigToHash(big.NewInt(1)), }, - want: core.NilHash, wantErr: errors.New("maxAltBlocks error"), }, { @@ -273,6 +274,7 @@ func TestPropose(t *testing.T) { salt: saltBytes32, iteration: 1, numOfProposedBlocks: 4, + sortedProposedBlockIds: []uint32{2, 0, 1, 3}, maxAltBlocks: 2, lastIteration: big.NewInt(5), lastProposedBlockStructErr: errors.New("lastProposedBlockStruct error"), @@ -281,22 +283,22 @@ func TestPropose(t *testing.T) { proposeTxn: &Types.Transaction{}, hash: common.BigToHash(big.NewInt(1)), }, - want: core.NilHash, wantErr: errors.New("lastProposedBlockStruct error"), }, { name: "Test 10: When numOfProposedBlocks >= maxAltBlocks and current iteration is greater than iteration of last proposed block ", args: args{ - state: 2, - staker: bindings.StructsStaker{}, - numStakers: 5, - biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), - biggestStakerId: 2, - salt: saltBytes32, - iteration: 2, - numOfProposedBlocks: 4, - maxAltBlocks: 2, - lastIteration: big.NewInt(5), + state: 2, + staker: bindings.StructsStaker{}, + numStakers: 5, + biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), + biggestStakerId: 2, + salt: saltBytes32, + iteration: 2, + numOfProposedBlocks: 4, + sortedProposedBlockIds: []uint32{2, 0, 1, 3}, + maxAltBlocks: 2, + lastIteration: big.NewInt(5), lastProposedBlockStruct: bindings.StructsBlock{ Iteration: big.NewInt(1), }, @@ -305,22 +307,22 @@ func TestPropose(t *testing.T) { proposeTxn: &Types.Transaction{}, hash: common.BigToHash(big.NewInt(1)), }, - want: core.NilHash, wantErr: nil, }, { name: "Test 11: When numOfProposedBlocks >= maxAltBlocks and current iteration is less than iteration of last proposed block and propose transaction is successful", args: args{ - state: 2, - staker: bindings.StructsStaker{}, - numStakers: 5, - biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), - biggestStakerId: 2, - salt: saltBytes32, - iteration: 1, - numOfProposedBlocks: 4, - maxAltBlocks: 2, - lastIteration: big.NewInt(5), + state: 2, + staker: bindings.StructsStaker{}, + numStakers: 5, + biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), + biggestStakerId: 2, + salt: saltBytes32, + iteration: 1, + numOfProposedBlocks: 4, + sortedProposedBlockIds: []uint32{2, 0, 1, 3}, + maxAltBlocks: 2, + lastIteration: big.NewInt(5), lastProposedBlockStruct: bindings.StructsBlock{ Iteration: big.NewInt(2), }, @@ -329,11 +331,35 @@ func TestPropose(t *testing.T) { proposeTxn: &Types.Transaction{}, hash: common.BigToHash(big.NewInt(1)), }, - want: common.BigToHash(big.NewInt(1)), wantErr: nil, }, { - name: "Test 12: When there is an error in getting medians", + name: "Test 12: When numOfProposedBlocks >= maxAltBlocks and there is an error in fetching sortedProposedBlockIds", + args: args{ + state: 2, + staker: bindings.StructsStaker{}, + numStakers: 5, + biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), + biggestStakerId: 2, + salt: saltBytes32, + iteration: 1, + numOfProposedBlocks: 4, + sortedProposedBlockIds: nil, + sortedProposedBlocksIdsErr: errors.New("error in fetching sorted proposed block ids"), + maxAltBlocks: 2, + lastIteration: big.NewInt(5), + lastProposedBlockStruct: bindings.StructsBlock{ + Iteration: big.NewInt(2), + }, + medians: []*big.Int{big.NewInt(6701548), big.NewInt(478307)}, + txnOpts: txnOpts, + proposeTxn: &Types.Transaction{}, + hash: common.BigToHash(big.NewInt(1)), + }, + wantErr: errors.New("error in fetching sorted proposed block ids"), + }, + { + name: "Test 13: When there is an error in getting medians", args: args{ state: 2, staker: bindings.StructsStaker{}, @@ -343,6 +369,7 @@ func TestPropose(t *testing.T) { salt: saltBytes32, iteration: 1, numOfProposedBlocks: 2, + sortedProposedBlockIds: []uint32{2, 0}, maxAltBlocks: 4, lastIteration: big.NewInt(5), lastProposedBlockStruct: bindings.StructsBlock{}, @@ -351,11 +378,10 @@ func TestPropose(t *testing.T) { proposeTxn: &Types.Transaction{}, hash: common.BigToHash(big.NewInt(1)), }, - want: core.NilHash, wantErr: errors.New("makeBlock error"), }, { - name: "Test 13: When Propose transaction fails", + name: "Test 14: When Propose transaction fails", args: args{ state: 2, staker: bindings.StructsStaker{}, @@ -365,6 +391,7 @@ func TestPropose(t *testing.T) { salt: saltBytes32, iteration: 1, numOfProposedBlocks: 2, + sortedProposedBlockIds: []uint32{2, 0}, maxAltBlocks: 4, lastIteration: big.NewInt(5), lastProposedBlockStruct: bindings.StructsBlock{}, @@ -373,11 +400,10 @@ func TestPropose(t *testing.T) { proposeErr: errors.New("propose error"), hash: common.BigToHash(big.NewInt(1)), }, - want: core.NilHash, wantErr: errors.New("propose error"), }, { - name: "Test 14: When there is an error in getting fileName", + name: "Test 15: When there is an error in getting fileName", args: args{ state: 2, staker: bindings.StructsStaker{}, @@ -387,19 +413,20 @@ func TestPropose(t *testing.T) { salt: saltBytes32, iteration: 1, numOfProposedBlocks: 3, + sortedProposedBlockIds: []uint32{2, 0, 1}, maxAltBlocks: 4, lastIteration: big.NewInt(5), lastProposedBlockStruct: bindings.StructsBlock{}, medians: []*big.Int{big.NewInt(6701548), big.NewInt(478307)}, txnOpts: txnOpts, proposeTxn: &Types.Transaction{}, + hash: common.BigToHash(big.NewInt(1)), fileNameErr: errors.New("fileName error"), }, - want: core.NilHash, - wantErr: nil, + wantErr: errors.New("fileName error"), }, { - name: "Test 15: When there is an error in saving data to file", + name: "Test 16: When there is an error in saving data to file", args: args{ state: 2, staker: bindings.StructsStaker{}, @@ -409,16 +436,17 @@ func TestPropose(t *testing.T) { salt: saltBytes32, iteration: 1, numOfProposedBlocks: 3, + sortedProposedBlockIds: []uint32{2, 0, 1}, maxAltBlocks: 4, lastIteration: big.NewInt(5), lastProposedBlockStruct: bindings.StructsBlock{}, medians: []*big.Int{big.NewInt(6701548), big.NewInt(478307)}, txnOpts: txnOpts, proposeTxn: &Types.Transaction{}, + hash: common.BigToHash(big.NewInt(1)), saveDataErr: errors.New("error in saving data"), }, - want: core.NilHash, - wantErr: nil, + wantErr: errors.New("error in saving data"), }, { name: "Test 17: When there is an error in getting buffer percent", @@ -430,7 +458,6 @@ func TestPropose(t *testing.T) { biggestStakerId: 2, bufferPercentErr: errors.New("buffer error"), }, - want: core.NilHash, wantErr: errors.New("buffer error"), }, { @@ -450,6 +477,7 @@ func TestPropose(t *testing.T) { salt: saltBytes32, iteration: 1, numOfProposedBlocks: 3, + sortedProposedBlockIds: []uint32{2, 0, 1}, maxAltBlocks: 4, lastIteration: big.NewInt(5), lastProposedBlockStruct: bindings.StructsBlock{}, @@ -458,7 +486,6 @@ func TestPropose(t *testing.T) { proposeTxn: &Types.Transaction{}, hash: common.BigToHash(big.NewInt(1)), }, - want: common.BigToHash(big.NewInt(1)), wantErr: nil, }, { @@ -477,6 +504,7 @@ func TestPropose(t *testing.T) { salt: saltBytes32, iteration: 1, numOfProposedBlocks: 3, + sortedProposedBlockIds: []uint32{2, 0, 1}, maxAltBlocks: 4, lastIteration: big.NewInt(5), lastProposedBlockStruct: bindings.StructsBlock{}, @@ -485,9 +513,31 @@ func TestPropose(t *testing.T) { proposeTxn: &Types.Transaction{}, hash: common.BigToHash(big.NewInt(1)), }, - want: core.NilHash, wantErr: errors.New("smallestStakerId error"), }, + { + name: "Test 20: When there is an error in waitForCompletion", + args: args{ + state: 2, + staker: bindings.StructsStaker{}, + numStakers: 5, + biggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), + biggestStakerId: 2, + salt: saltBytes32, + iteration: 1, + numOfProposedBlocks: 3, + sortedProposedBlockIds: []uint32{2, 0, 1}, + maxAltBlocks: 4, + lastIteration: big.NewInt(5), + lastProposedBlockStruct: bindings.StructsBlock{}, + medians: []*big.Int{big.NewInt(6701548), big.NewInt(478307)}, + txnOpts: txnOpts, + proposeTxn: &Types.Transaction{}, + hash: common.BigToHash(big.NewInt(1)), + waitForBlockCompletionErr: errors.New("waitForBlockCompletion error"), + }, + wantErr: errors.New("waitForBlockCompletion error"), + }, } for _, tt := range tests { @@ -511,6 +561,7 @@ func TestPropose(t *testing.T) { cmdUtilsMock.On("GetSalt", mock.AnythingOfType("*ethclient.Client"), mock.Anything).Return(tt.args.salt, tt.args.saltErr) cmdUtilsMock.On("GetIteration", mock.Anything, mock.Anything).Return(tt.args.iteration) utilsMock.On("GetNumberOfProposedBlocks", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32")).Return(tt.args.numOfProposedBlocks, tt.args.numOfProposedBlocksErr) + utilsMock.On("GetSortedProposedBlockIds", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32")).Return(tt.args.sortedProposedBlockIds, tt.args.sortedProposedBlocksIdsErr) utilsMock.On("GetMaxAltBlocks", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return(tt.args.maxAltBlocks, tt.args.maxAltBlocksErr) utilsMock.On("GetProposedBlock", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32"), mock.AnythingOfType("uint32")).Return(tt.args.lastProposedBlockStruct, tt.args.lastProposedBlockStructErr) cmdUtilsMock.On("MakeBlock", mock.AnythingOfType("*ethclient.Client"), mock.Anything, mock.Anything, mock.Anything).Return(tt.args.medians, tt.args.ids, tt.args.revealDataMaps, tt.args.mediansErr) @@ -521,13 +572,11 @@ func TestPropose(t *testing.T) { blockManagerUtilsMock.On("Propose", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.proposeTxn, tt.args.proposeErr) transactionUtilsMock.On("Hash", mock.Anything).Return(tt.args.hash) cmdUtilsMock.On("GetBufferPercent").Return(tt.args.bufferPercent, tt.args.bufferPercentErr) + utilsMock.On("WaitForBlockCompletion", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return(tt.args.waitForBlockCompletionErr) utils := &UtilsStruct{} t.Run(tt.name, func(t *testing.T) { - got, err := utils.Propose(client, config, account, staker, epoch, blockNumber, tt.args.rogueData) - if got != tt.want { - t.Errorf("Txn hash for Propose function, got = %v, want %v", got, tt.want) - } + err := utils.Propose(client, config, account, staker, epoch, blockNumber, tt.args.rogueData) if err == nil || tt.wantErr == nil { if err != tt.wantErr { t.Errorf("Error for Propose function, got = %v, want %v", err, tt.wantErr) diff --git a/cmd/resetUnstakeLock.go b/cmd/resetUnstakeLock.go index fa079f9d..5da926b8 100644 --- a/cmd/resetUnstakeLock.go +++ b/cmd/resetUnstakeLock.go @@ -35,6 +35,7 @@ func initialiseExtendLock(cmd *cobra.Command, args []string) { func (*UtilsStruct) ExecuteExtendLock(flagSet *pflag.FlagSet) { config, err := cmdUtils.GetConfigData() utils.CheckError("Error in getting config: ", err) + log.Debugf("ExecuteExtendLock: Config: %+v", config) client := razorUtils.ConnectToClient(config.Provider) @@ -42,9 +43,11 @@ func (*UtilsStruct) ExecuteExtendLock(flagSet *pflag.FlagSet) { utils.CheckError("Error in getting address: ", err) logger.SetLoggerParameters(client, address) + log.Debug("Checking to assign log file...") razorUtils.AssignLogFile(flagSet) - password := razorUtils.AssignPassword() + log.Debug("Getting password...") + password := razorUtils.AssignPassword(flagSet) stakerId, err := razorUtils.AssignStakerId(flagSet, client, address) utils.CheckError("Error in getting stakerId: ", err) @@ -54,6 +57,7 @@ func (*UtilsStruct) ExecuteExtendLock(flagSet *pflag.FlagSet) { Password: password, StakerId: stakerId, } + log.Debugf("ExecuteExtendLock: Calling ResetUnstakeLock with arguments extendLockInput = %+v", extendLockInput) txn, err := cmdUtils.ResetUnstakeLock(client, config, extendLockInput) utils.CheckError("Error in extending lock: ", err) err = razorUtils.WaitForBlockCompletion(client, txn.String()) @@ -75,6 +79,7 @@ func (*UtilsStruct) ResetUnstakeLock(client *ethclient.Client, config types.Conf }) log.Info("Extending lock...") + log.Debug("Executing ResetUnstakeLock transaction with stakerId = ", extendLockInput.StakerId) txn, err := stakeManagerUtils.ResetUnstakeLock(client, txnOpts, extendLockInput.StakerId) if err != nil { return core.NilHash, err @@ -88,10 +93,12 @@ func init() { var ( Address string + Password string StakerId uint32 ) extendUnstakeLockCmd.Flags().StringVarP(&Address, "address", "a", "", "address of the user") + extendUnstakeLockCmd.Flags().StringVarP(&Password, "password", "", "", "password path of the user to protect the keystore") extendUnstakeLockCmd.Flags().Uint32VarP(&StakerId, "stakerId", "", 0, "staker id") addrErr := extendUnstakeLockCmd.MarkFlagRequired("address") diff --git a/cmd/resetUnstakeLock_test.go b/cmd/resetUnstakeLock_test.go index f6790b6f..55b1f4fa 100644 --- a/cmd/resetUnstakeLock_test.go +++ b/cmd/resetUnstakeLock_test.go @@ -196,7 +196,7 @@ func TestExecuteExtendLock(t *testing.T) { utilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet")) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) - utilsMock.On("AssignPassword").Return(tt.args.password) + utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) flagSetUtilsMock.On("GetStringAddress", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.address, tt.args.addressErr) utilsMock.On("AssignStakerId", flagSet, mock.AnythingOfType("*ethclient.Client"), mock.Anything).Return(tt.args.stakerId, tt.args.stakerIdErr) utilsMock.On("ConnectToClient", mock.AnythingOfType("string")).Return(client) diff --git a/cmd/reveal.go b/cmd/reveal.go index f668dd5c..0558bc87 100644 --- a/cmd/reveal.go +++ b/cmd/reveal.go @@ -21,7 +21,7 @@ func (*UtilsStruct) HandleRevealState(client *ethclient.Client, staker bindings. if err != nil { return err } - log.Debug("Staker last epoch committed: ", epochLastCommitted) + log.Debug("HandleRevealState: Staker last epoch committed: ", epochLastCommitted) if epochLastCommitted != epoch { return errors.New("commitment for this epoch not found on network.... aborting reveal") } @@ -35,7 +35,9 @@ func (*UtilsStruct) Reveal(client *ethclient.Client, config types.Configurations return core.NilHash, err } + log.Debug("Creating merkle tree...") merkleTree := utils.MerkleInterface.CreateMerkle(commitData.Leaves) + log.Debug("Generating tree reveal data...") treeRevealData := cmdUtils.GenerateTreeRevealData(merkleTree, commitData) log.Debugf("Revealing vote for epoch: %d, commitAccount: %s, treeRevealData: %v, root: %v", @@ -58,6 +60,7 @@ func (*UtilsStruct) Reveal(client *ethclient.Client, config types.Configurations MethodName: "reveal", Parameters: []interface{}{epoch, treeRevealData, signature}, }) + log.Debugf("Executing Reveal transaction wih epoch = %d, treeRevealData = %v, signature = %v", epoch, treeRevealData, signature) txn, err := voteManagerUtils.Reveal(client, txnOpts, epoch, treeRevealData, signature) if err != nil { log.Error(err) @@ -87,20 +90,24 @@ func (*UtilsStruct) GenerateTreeRevealData(merkleTree [][][]byte, commitData typ values = append(values, value) proofs = append(proofs, proof) } + root := utils.MerkleInterface.GetMerkleRoot(merkleTree) + log.Debugf("GenerateTreeRevealData: values = %+v, proofs = %+v, root = %v", values, proofs, root) return bindings.StructsMerkleTree{ Values: values, Proofs: proofs, - Root: utils.MerkleInterface.GetMerkleRoot(merkleTree), + Root: root, } } //This function indexes the reveal events of current epoch func (*UtilsStruct) IndexRevealEventsOfCurrentEpoch(client *ethclient.Client, blockNumber *big.Int, epoch uint32) ([]types.RevealedStruct, error) { + log.Debug("Fetching reveal events of current epoch...") fromBlock, err := utils.UtilsInterface.CalculateBlockNumberAtEpochBeginning(client, core.EpochLength, blockNumber) if err != nil { return nil, errors.New("Not able to Fetch Block: " + err.Error()) } + log.Debugf("IndexRevealEventsOfCurrentEpoch: Checking for events from block: %s to block: %s", fromBlock, blockNumber) query := ethereum.FilterQuery{ FromBlock: fromBlock, ToBlock: blockNumber, @@ -108,6 +115,7 @@ func (*UtilsStruct) IndexRevealEventsOfCurrentEpoch(client *ethclient.Client, bl common.HexToAddress(core.VoteManagerAddress), }, } + log.Debugf("IndexRevealEventsOfCurrentEpoch: Query to send in filter logs: %+v", query) logs, err := utils.UtilsInterface.FilterLogsWithRetry(client, query) if err != nil { return nil, err @@ -120,7 +128,7 @@ func (*UtilsStruct) IndexRevealEventsOfCurrentEpoch(client *ethclient.Client, bl for _, vLog := range logs { data, unpackErr := abiUtils.Unpack(contractAbi, "Revealed", vLog.Data) if unpackErr != nil { - log.Error(unpackErr) + log.Debug(unpackErr) continue } if epoch == data[0].(uint32) { @@ -142,6 +150,6 @@ func (*UtilsStruct) IndexRevealEventsOfCurrentEpoch(client *ethclient.Client, bl revealedData = append(revealedData, consolidatedRevealedData) } } - log.Debug("Revealed values: ", revealedData) + log.Debug("IndexRevealEventsOfCurrentEpoch: Revealed values: ", revealedData) return revealedData, nil } diff --git a/cmd/root.go b/cmd/root.go index dacf3599..833d7792 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -21,6 +21,7 @@ var ( LogLevel string GasLimitMultiplier float32 LogFile string + RPCTimeout int64 ) var log = logger.NewLogger() @@ -61,6 +62,7 @@ func init() { rootCmd.PersistentFlags().StringVarP(&LogLevel, "logLevel", "", "", "log level") rootCmd.PersistentFlags().Float32VarP(&GasLimitMultiplier, "gasLimit", "", -1, "gas limit percentage increase") rootCmd.PersistentFlags().StringVarP(&LogFile, "logFile", "", "", "name of log file") + rootCmd.PersistentFlags().Int64VarP(&RPCTimeout, "rpcTimeout", "", 0, "RPC timeout if its not responding") rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") } @@ -108,4 +110,5 @@ func setLogLevel() { log.Debugf("Gas Price: %d", config.GasPrice) log.Debugf("Log Level: %s", config.LogLevel) log.Debugf("Gas Limit: %.2f", config.GasLimitMultiplier) + log.Debugf("RPC Timeout: %d", config.RPCTimeout) } diff --git a/cmd/setConfig.go b/cmd/setConfig.go index 81f5160b..bc91acfd 100644 --- a/cmd/setConfig.go +++ b/cmd/setConfig.go @@ -2,10 +2,10 @@ package cmd import ( + "razor/core" "razor/metrics" "razor/utils" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/spf13/viper" @@ -28,6 +28,7 @@ Example: //This function returns the error if there is any and sets the config func (*UtilsStruct) SetConfig(flagSet *pflag.FlagSet) error { + log.Debug("Checking to assign log file...") razorUtils.AssignLogFile(flagSet) provider, err := flagSetUtils.GetStringProvider(flagSet) if err != nil { @@ -57,6 +58,10 @@ func (*UtilsStruct) SetConfig(flagSet *pflag.FlagSet) error { if err != nil { return err } + rpcTimeout, rpcTimeoutErr := flagSetUtils.GetInt64RPCTimeout(flagSet) + if rpcTimeoutErr != nil { + return rpcTimeoutErr + } path, pathErr := razorUtils.GetConfigFilePath() if pathErr != nil { @@ -88,7 +93,7 @@ func (*UtilsStruct) SetConfig(flagSet *pflag.FlagSet) error { err = metrics.Run(port, certFile, certKey) if err != nil { - logrus.Errorf("failed to start metrics http server: %s", err) + log.Error("Failed to start metrics http server: ", err) } } if provider != "" { @@ -112,14 +117,18 @@ func (*UtilsStruct) SetConfig(flagSet *pflag.FlagSet) error { if gasLimit != -1 { viper.Set("gasLimit", gasLimit) } - if provider == "" && gasMultiplier == -1 && bufferPercent == 0 && waitTime == -1 && gasPrice == -1 && logLevel == "" && gasLimit == -1 { - viper.Set("provider", "http://127.0.0.1:8545") - viper.Set("gasmultiplier", 1.0) - viper.Set("buffer", 20) - viper.Set("wait", 3) - viper.Set("gasprice", 1) - viper.Set("logLevel", "") - viper.Set("gasLimit", 2) + if rpcTimeout != 0 { + viper.Set("rpcTimeout", rpcTimeout) + } + if provider == "" && gasMultiplier == -1 && bufferPercent == 0 && waitTime == -1 && gasPrice == -1 && logLevel == "" && gasLimit == -1 && rpcTimeout == 0 { + viper.Set("provider", core.DefaultProvider) + viper.Set("gasmultiplier", core.DefaultGasMultiplier) + viper.Set("buffer", core.DefaultBufferPercent) + viper.Set("wait", core.DefaultWaitTime) + viper.Set("gasprice", core.DefaultGasPrice) + viper.Set("logLevel", core.DefaultLogLevel) + viper.Set("gasLimit", core.DefaultGasLimit) + viper.Set("rpcTimeout", core.DefaultRPCTimeout) //viper.Set("exposeMetricsPort", "") log.Info("Config values set to default. Use setConfig to modify the values.") } @@ -143,6 +152,7 @@ func init() { GasPrice int32 LogLevel string GasLimitMultiplier float32 + RPCTimeout int64 ExposeMetrics string CertFile string CertKey string @@ -154,6 +164,7 @@ func init() { setConfig.Flags().Int32VarP(&GasPrice, "gasprice", "", -1, "custom gas price") setConfig.Flags().StringVarP(&LogLevel, "logLevel", "", "", "log level") setConfig.Flags().Float32VarP(&GasLimitMultiplier, "gasLimit", "", -1, "gas limit percentage increase") + setConfig.Flags().Int64VarP(&RPCTimeout, "rpcTimeout", "", 0, "RPC timeout if its not responding") setConfig.Flags().StringVarP(&ExposeMetrics, "exposeMetrics", "", "", "port number") setConfig.Flags().StringVarP(&CertFile, "certFile", "", "", "ssl certificate path") setConfig.Flags().StringVarP(&CertKey, "certKey", "", "", "ssl certificate key path") diff --git a/cmd/setConfig_test.go b/cmd/setConfig_test.go index 7c0617b1..23c32b80 100644 --- a/cmd/setConfig_test.go +++ b/cmd/setConfig_test.go @@ -31,6 +31,8 @@ func TestSetConfig(t *testing.T) { configErr error gasLimitMultiplier float32 gasLimitMultiplierErr error + rpcTimeout int64 + rpcTimeoutErr error isFlagPassed bool port string portErr error @@ -57,6 +59,7 @@ func TestSetConfig(t *testing.T) { configErr: nil, gasLimitMultiplier: 10, gasLimitMultiplierErr: nil, + rpcTimeout: 10, }, wantErr: nil, }, @@ -73,6 +76,7 @@ func TestSetConfig(t *testing.T) { configErr: nil, gasLimitMultiplier: 10, gasLimitMultiplierErr: nil, + rpcTimeout: 0, }, wantErr: nil, }, @@ -262,6 +266,22 @@ func TestSetConfig(t *testing.T) { }, wantErr: errors.New("error in getting port"), }, + { + name: "Test 16: When there is an error in getting RPC timeout", + args: args{ + provider: "http://127.0.0.1", + gasmultiplier: 2, + buffer: 20, + waitTime: 2, + gasPrice: 1, + logLevel: "debug", + path: "/home/config", + configErr: nil, + gasLimitMultiplier: -1, + rpcTimeoutErr: errors.New("rpcTimeout error"), + }, + wantErr: errors.New("rpcTimeout error"), + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -284,6 +304,7 @@ func TestSetConfig(t *testing.T) { flagSetUtilsMock.On("GetInt32GasPrice", flagSet).Return(tt.args.gasPrice, tt.args.gasPriceErr) flagSetUtilsMock.On("GetStringLogLevel", flagSet).Return(tt.args.logLevel, tt.args.logLevelErr) flagSetUtilsMock.On("GetFloat32GasLimit", flagSet).Return(tt.args.gasLimitMultiplier, tt.args.gasLimitMultiplierErr) + flagSetUtilsMock.On("GetInt64RPCTimeout", flagSet).Return(tt.args.rpcTimeout, tt.args.rpcTimeoutErr) flagSetUtilsMock.On("GetStringExposeMetrics", flagSet).Return(tt.args.port, tt.args.portErr) flagSetUtilsMock.On("GetStringCertFile", flagSet).Return(tt.args.certFile, tt.args.certFileErr) flagSetUtilsMock.On("GetStringCertKey", flagSet).Return(tt.args.certKey, tt.args.certKeyErr) diff --git a/cmd/setDelegation.go b/cmd/setDelegation.go index 80445983..bfa90dee 100644 --- a/cmd/setDelegation.go +++ b/cmd/setDelegation.go @@ -35,6 +35,7 @@ func initialiseSetDelegation(cmd *cobra.Command, args []string) { func (*UtilsStruct) ExecuteSetDelegation(flagSet *pflag.FlagSet) { config, err := cmdUtils.GetConfigData() utils.CheckError("Error in getting config: ", err) + log.Debugf("ExecuteSetDelegation: Config: %+v", config) client := razorUtils.ConnectToClient(config.Provider) @@ -42,9 +43,11 @@ func (*UtilsStruct) ExecuteSetDelegation(flagSet *pflag.FlagSet) { utils.CheckError("Error in getting address: ", err) logger.SetLoggerParameters(client, address) + log.Debug("Checking to assign log file...") razorUtils.AssignLogFile(flagSet) - password := razorUtils.AssignPassword() + log.Debug("Getting password...") + password := razorUtils.AssignPassword(flagSet) statusString, err := flagSetUtils.GetStringStatus(flagSet) utils.CheckError("Error in getting status: ", err) @@ -66,6 +69,7 @@ func (*UtilsStruct) ExecuteSetDelegation(flagSet *pflag.FlagSet) { Commission: commission, } + log.Debugf("ExecuteSetDelegation: Calling SetDelegation() with argument delegationInput = %+v", delegationInput) txn, err := cmdUtils.SetDelegation(client, config, delegationInput) utils.CheckError("SetDelegation error: ", err) if txn != core.NilHash { @@ -80,13 +84,16 @@ func (*UtilsStruct) SetDelegation(client *ethclient.Client, config types.Configu if err != nil { return core.NilHash, err } + log.Debugf("SetDelegation: Staker Info: %+v", stakerInfo) if delegationInput.Commission != 0 { - err = cmdUtils.UpdateCommission(config, client, types.UpdateCommissionInput{ + updateCommissionInput := types.UpdateCommissionInput{ StakerId: delegationInput.StakerId, Address: delegationInput.Address, Password: delegationInput.Password, Commission: delegationInput.Commission, - }) + } + log.Debugf("Calling UpdateCommission() with argument updateCommissionInput = %+v", updateCommissionInput) + err = cmdUtils.UpdateCommission(config, client, updateCommissionInput) if err != nil { return core.NilHash, err } @@ -110,6 +117,7 @@ func (*UtilsStruct) SetDelegation(client *ethclient.Client, config types.Configu } log.Infof("Setting delegation acceptance of Staker %d to %t", delegationInput.StakerId, delegationInput.Status) setDelegationAcceptanceTxnOpts := razorUtils.GetTxnOpts(txnOpts) + log.Debug("Executing SetDelegationAcceptance transaction with status ", delegationInput.Status) delegationAcceptanceTxn, err := stakeManagerUtils.SetDelegationAcceptance(client, setDelegationAcceptanceTxnOpts, delegationInput.Status) if err != nil { log.Error("Error in setting delegation acceptance") @@ -126,11 +134,13 @@ func init() { var ( Status string Address string + Password string Commission uint8 ) setDelegationCmd.Flags().StringVarP(&Status, "status", "s", "true", "true for accepting delegation and false for not accepting") setDelegationCmd.Flags().StringVarP(&Address, "address", "a", "", "your account address") + setDelegationCmd.Flags().StringVarP(&Password, "password", "", "", "password path to protect the keystore") setDelegationCmd.Flags().Uint8VarP(&Commission, "commission", "c", 0, "commission") addrErr := setDelegationCmd.MarkFlagRequired("address") diff --git a/cmd/setDelegation_test.go b/cmd/setDelegation_test.go index 1c3208e7..9e7bf53c 100644 --- a/cmd/setDelegation_test.go +++ b/cmd/setDelegation_test.go @@ -414,7 +414,7 @@ func TestExecuteSetDelegation(t *testing.T) { utilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet")) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) - utilsMock.On("AssignPassword").Return(tt.args.password) + utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) flagSetUtilsMock.On("GetStringAddress", flagSet).Return(tt.args.address, tt.args.addressErr) flagSetUtilsMock.On("GetStringStatus", flagSet).Return(tt.args.status, tt.args.statusErr) flagSetUtilsMock.On("GetUint8Commission", flagSet).Return(tt.args.commission, tt.args.commissionErr) diff --git a/cmd/stakerInfo.go b/cmd/stakerInfo.go index fdbc688d..0778117e 100644 --- a/cmd/stakerInfo.go +++ b/cmd/stakerInfo.go @@ -31,13 +31,16 @@ func initialiseStakerInfo(cmd *cobra.Command, args []string) { func (*UtilsStruct) ExecuteStakerinfo(flagSet *pflag.FlagSet) { config, err := cmdUtils.GetConfigData() utils.CheckError("Error in getting config: ", err) + log.Debugf("ExecuteStakerinfo: Config: %+v", config) client := razorUtils.ConnectToClient(config.Provider) logger.SetLoggerParameters(client, "") stakerId, err := flagSetUtils.GetUint32StakerId(flagSet) utils.CheckError("Error in getting stakerId: ", err) + log.Debug("ExecuteStakerinfo: StakerId: ", stakerId) + log.Debug("ExecuteStakerinfo: Calling GetStakerInfo() with argument stakerId = ", stakerId) err = cmdUtils.GetStakerInfo(client, stakerId) utils.CheckError("Error in getting staker info: ", err) diff --git a/cmd/struct-utils.go b/cmd/struct-utils.go index 18a5a59a..5d93faab 100644 --- a/cmd/struct-utils.go +++ b/cmd/struct-utils.go @@ -56,6 +56,15 @@ func InitializeUtils() { utils.FlagSetInterface = &utils.FlagSetStruct{} } +func ExecuteTransaction(interfaceName interface{}, methodName string, args ...interface{}) (*Types.Transaction, error) { + returnedValues := utils.InvokeFunctionWithTimeout(interfaceName, methodName, args...) + returnedError := utils.CheckIfAnyError(returnedValues) + if returnedError != nil { + return nil, returnedError + } + return returnedValues[0].Interface().(*Types.Transaction), nil +} + //This function returns the config file path func (u Utils) GetConfigFilePath() (string, error) { return path.PathUtilsInterface.GetConfigFilePath() @@ -87,8 +96,8 @@ func (u Utils) GetConfigData() (types.Configurations, error) { } //This function assigns the password -func (u Utils) AssignPassword() string { - return utils.AssignPassword() +func (u Utils) AssignPassword(flagSet *pflag.FlagSet) string { + return utils.AssignPassword(flagSet) } //This function returns the string address @@ -103,7 +112,12 @@ func (u Utils) GetUint32BountyId(flagSet *pflag.FlagSet) (uint32, error) { //This function connects to the client func (u Utils) ConnectToClient(provider string) *ethclient.Client { - return utilsInterface.ConnectToClient(provider) + returnedValues := utils.InvokeFunctionWithTimeout(utilsInterface, "ConnectToClient", provider) + returnedError := utils.CheckIfAnyError(returnedValues) + if returnedError != nil { + return nil + } + return returnedValues[0].Interface().(*ethclient.Client) } //This function waits for the block completion @@ -276,6 +290,11 @@ func (u Utils) GetEpochLastRevealed(client *ethclient.Client, stakerId uint32) ( return utilsInterface.GetEpochLastRevealed(client, stakerId) } +//This function returns the epoch which is last proposed +func (u Utils) GetEpochLastProposed(client *ethclient.Client, stakerId uint32) (uint32, error) { + return utilsInterface.GetEpochLastProposed(client, stakerId) +} + //This function returns the vote value func (u Utils) GetVoteValue(client *ethclient.Client, epoch uint32, stakerId uint32, medianIndex uint16) (*big.Int, error) { return utilsInterface.GetVoteValue(client, epoch, stakerId, medianIndex) @@ -392,8 +411,8 @@ func (u Utils) ReadFromProposeJsonFile(filePath string) (types.ProposeFileData, } //This function saves the data to propose JSON file -func (u Utils) SaveDataToProposeJsonFile(flePath string, epoch uint32, proposeFileData types.ProposeData) error { - return utilsInterface.SaveDataToProposeJsonFile(flePath, epoch, proposeFileData) +func (u Utils) SaveDataToProposeJsonFile(flePath string, proposeFileData types.ProposeFileData) error { + return utilsInterface.SaveDataToProposeJsonFile(flePath, proposeFileData) } //This function saves data to Dispute JSON file @@ -429,92 +448,126 @@ func (transactionUtils TransactionUtils) Hash(txn *Types.Transaction) common.Has //This function is of staking the razors func (stakeManagerUtils StakeManagerUtils) Stake(client *ethclient.Client, txnOpts *bind.TransactOpts, epoch uint32, amount *big.Int) (*Types.Transaction, error) { stakeManager := utilsInterface.GetStakeManager(client) - return stakeManager.Stake(txnOpts, epoch, amount) + return ExecuteTransaction(stakeManager, "Stake", txnOpts, epoch, amount) } //This function resets the unstake lock func (stakeManagerUtils StakeManagerUtils) ResetUnstakeLock(client *ethclient.Client, opts *bind.TransactOpts, stakerId uint32) (*Types.Transaction, error) { stakeManager := utilsInterface.GetStakeManager(client) - return stakeManager.ResetUnstakeLock(opts, stakerId) + return ExecuteTransaction(stakeManager, "ResetUnstakeLock", opts, stakerId) } //This function is for delegation func (stakeManagerUtils StakeManagerUtils) Delegate(client *ethclient.Client, opts *bind.TransactOpts, stakerId uint32, amount *big.Int) (*Types.Transaction, error) { stakeManager := utilsInterface.GetStakeManager(client) - return stakeManager.Delegate(opts, stakerId, amount) + return ExecuteTransaction(stakeManager, "Delegate", opts, stakerId, amount) } //This function initiates the withdraw func (stakeManagerUtils StakeManagerUtils) InitiateWithdraw(client *ethclient.Client, opts *bind.TransactOpts, stakerId uint32) (*Types.Transaction, error) { stakeManager := utilsInterface.GetStakeManager(client) - return stakeManager.InitiateWithdraw(opts, stakerId) + return ExecuteTransaction(stakeManager, "InitiateWithdraw", opts, stakerId) } //This function unlocks the withdraw amount func (stakeManagerUtils StakeManagerUtils) UnlockWithdraw(client *ethclient.Client, opts *bind.TransactOpts, stakerId uint32) (*Types.Transaction, error) { stakeManager := utilsInterface.GetStakeManager(client) - return stakeManager.UnlockWithdraw(opts, stakerId) + return ExecuteTransaction(stakeManager, "UnlockWithdraw", opts, stakerId) } //This function sets the delegation acceptance or rejection func (stakeManagerUtils StakeManagerUtils) SetDelegationAcceptance(client *ethclient.Client, opts *bind.TransactOpts, status bool) (*Types.Transaction, error) { stakeManager := utilsInterface.GetStakeManager(client) - return stakeManager.SetDelegationAcceptance(opts, status) + return ExecuteTransaction(stakeManager, "SetDelegationAcceptance", opts, status) } //This function updates the commission func (stakeManagerUtils StakeManagerUtils) UpdateCommission(client *ethclient.Client, opts *bind.TransactOpts, commission uint8) (*Types.Transaction, error) { stakeManager := utilsInterface.GetStakeManager(client) - return stakeManager.UpdateCommission(opts, commission) + return ExecuteTransaction(stakeManager, "UpdateCommission", opts, commission) } //This function allows to unstake the razors func (stakeManagerUtils StakeManagerUtils) Unstake(client *ethclient.Client, opts *bind.TransactOpts, stakerId uint32, sAmount *big.Int) (*Types.Transaction, error) { stakeManager := utilsInterface.GetStakeManager(client) - return stakeManager.Unstake(opts, stakerId, sAmount) + return ExecuteTransaction(stakeManager, "Unstake", opts, stakerId, sAmount) } //This function approves the unstake your razor func (stakeManagerUtils StakeManagerUtils) ApproveUnstake(client *ethclient.Client, opts *bind.TransactOpts, staker bindings.StructsStaker, amount *big.Int) (*Types.Transaction, error) { stakedToken := razorUtils.GetStakedToken(client, staker.TokenAddress) - return stakedToken.Approve(opts, common.HexToAddress(core.StakeManagerAddress), amount) + log.Debugf("ApproveUnstake: Executing Approve transaction for stakedToken address: %s with arguments amount : %s", staker.TokenAddress, amount) + return ExecuteTransaction(stakedToken, "Approve", opts, common.HexToAddress(core.StakeManagerAddress), amount) } //This function is used to redeem the bounty func (stakeManagerUtils StakeManagerUtils) RedeemBounty(client *ethclient.Client, opts *bind.TransactOpts, bountyId uint32) (*Types.Transaction, error) { stakeManager := utilsInterface.GetStakeManager(client) - return stakeManager.RedeemBounty(opts, bountyId) + return ExecuteTransaction(stakeManager, "RedeemBounty", opts, bountyId) } //This function returns the staker Info func (stakeManagerUtils StakeManagerUtils) StakerInfo(client *ethclient.Client, opts *bind.CallOpts, stakerId uint32) (types.Staker, error) { stakeManager := utilsInterface.GetStakeManager(client) - return stakeManager.Stakers(opts, stakerId) + returnedValues := utils.InvokeFunctionWithTimeout(stakeManager, "Stakers", opts, stakerId) + returnedError := utils.CheckIfAnyError(returnedValues) + if returnedError != nil { + return types.Staker{}, returnedError + } + staker := returnedValues[0].Interface().(struct { + AcceptDelegation bool + IsSlashed bool + Commission uint8 + Id uint32 + Age uint32 + Address common.Address + TokenAddress common.Address + EpochFirstStakedOrLastPenalized uint32 + EpochCommissionLastUpdated uint32 + Stake *big.Int + StakerReward *big.Int + }) + return staker, nil } //This function returns the maturity func (stakeManagerUtils StakeManagerUtils) GetMaturity(client *ethclient.Client, opts *bind.CallOpts, age uint32) (uint16, error) { stakeManager := utilsInterface.GetStakeManager(client) index := age / 10000 - return stakeManager.Maturities(opts, big.NewInt(int64(index))) + returnedValues := utils.InvokeFunctionWithTimeout(stakeManager, "Maturities", opts, big.NewInt(int64(index))) + returnedError := utils.CheckIfAnyError(returnedValues) + if returnedError != nil { + return 0, returnedError + } + return returnedValues[0].Interface().(uint16), nil } //This function returns the bounty lock func (stakeManagerUtils StakeManagerUtils) GetBountyLock(client *ethclient.Client, opts *bind.CallOpts, bountyId uint32) (types.BountyLock, error) { stakeManager := utilsInterface.GetStakeManager(client) - return stakeManager.BountyLocks(opts, bountyId) + returnedValues := utils.InvokeFunctionWithTimeout(stakeManager, "BountyLocks", opts, bountyId) + returnedError := utils.CheckIfAnyError(returnedValues) + if returnedError != nil { + return types.BountyLock{}, returnedError + } + bountyLock := returnedValues[0].Interface().(struct { + RedeemAfter uint32 + BountyHunter common.Address + Amount *big.Int + }) + return bountyLock, nil } //This function is used to claim the staker reward func (stakeManagerUtils StakeManagerUtils) ClaimStakeReward(client *ethclient.Client, opts *bind.TransactOpts) (*Types.Transaction, error) { stakeManager := utilsInterface.GetStakeManager(client) - return stakeManager.ClaimStakerReward(opts) + return ExecuteTransaction(stakeManager, "ClaimStakerReward", opts) } //This function is used to claim the block reward func (blockManagerUtils BlockManagerUtils) ClaimBlockReward(client *ethclient.Client, opts *bind.TransactOpts) (*Types.Transaction, error) { blockManager := utilsInterface.GetBlockManager(client) - return blockManager.ClaimBlockReward(opts) + return ExecuteTransaction(blockManager, "ClaimBlockReward", opts) } //Thid function is used to finalize the dispute @@ -525,7 +578,7 @@ func (blockManagerUtils BlockManagerUtils) FinalizeDispute(client *ethclient.Cli err error ) err = retry.Do(func() error { - txn, err = blockManager.FinalizeDispute(opts, epoch, blockIndex, positionOfCollectionInBlock) + txn, err = ExecuteTransaction(blockManager, "FinalizeDispute", opts, epoch, blockIndex, positionOfCollectionInBlock) if err != nil { log.Error("Error in finalizing dispute.. Retrying") return err @@ -546,7 +599,7 @@ func (blockManagerUtils BlockManagerUtils) DisputeBiggestStakeProposed(client *e err error ) err = retry.Do(func() error { - txn, err = blockManager.DisputeBiggestStakeProposed(opts, epoch, blockIndex, correctBiggestStakerId) + txn, err = ExecuteTransaction(blockManager, "DisputeBiggestStakeProposed", opts, epoch, blockIndex, correctBiggestStakerId) if err != nil { log.Error("Error in disputing biggest influence proposed.. Retrying") return err @@ -567,7 +620,8 @@ func (blockManagerUtils BlockManagerUtils) DisputeCollectionIdShouldBeAbsent(cli err error ) err = retry.Do(func() error { - txn, err = blockManager.DisputeCollectionIdShouldBeAbsent(opts, epoch, blockIndex, id, positionOfCollectionInBlock) + txn, err = ExecuteTransaction(blockManager, "DisputeCollectionIdShouldBeAbsent", opts, epoch, blockIndex, id, positionOfCollectionInBlock) + if err != nil { log.Error("Error in disputing collection id should be absent... Retrying") return err @@ -588,7 +642,7 @@ func (blockManagerUtils BlockManagerUtils) DisputeCollectionIdShouldBePresent(cl err error ) err = retry.Do(func() error { - txn, err = blockManager.DisputeCollectionIdShouldBePresent(opts, epoch, blockIndex, id) + txn, err = ExecuteTransaction(blockManager, "DisputeCollectionIdShouldBePresent", opts, epoch, blockIndex, id) if err != nil { log.Error("Error in disputing collection id should be present... Retrying") return err @@ -609,7 +663,7 @@ func (blockManagerUtils BlockManagerUtils) DisputeOnOrderOfIds(client *ethclient err error ) err = retry.Do(func() error { - txn, err = blockManager.DisputeOnOrderOfIds(opts, epoch, blockIndex, index0, index1) + txn, err = ExecuteTransaction(blockManager, "DisputeOnOrderOfIds", opts, epoch, blockIndex, index0, index1) if err != nil { log.Error("Error in disputing order of ids proposed... Retrying") return err @@ -630,7 +684,7 @@ func (blockManagerUtils BlockManagerUtils) Propose(client *ethclient.Client, opt err error ) err = retry.Do(func() error { - txn, err = blockManager.Propose(opts, epoch, ids, medians, iteration, biggestInfluencerId) + txn, err = ExecuteTransaction(blockManager, "Propose", opts, epoch, ids, medians, iteration, biggestInfluencerId) if err != nil { log.Error("Error in proposing... Retrying") return err @@ -645,12 +699,29 @@ func (blockManagerUtils BlockManagerUtils) Propose(client *ethclient.Client, opt //This function returns the sorted Ids func (blockManagerUtils BlockManagerUtils) GiveSorted(blockManager *bindings.BlockManager, opts *bind.TransactOpts, epoch uint32, leafId uint16, sortedValues []*big.Int) (*Types.Transaction, error) { - return blockManager.GiveSorted(opts, epoch, leafId, sortedValues) + return ExecuteTransaction(blockManager, "GiveSorted", opts, epoch, leafId, sortedValues) } //This function resets the dispute func (blockManagerUtils BlockManagerUtils) ResetDispute(blockManager *bindings.BlockManager, opts *bind.TransactOpts, epoch uint32) (*Types.Transaction, error) { - return blockManager.ResetDispute(opts, epoch) + return ExecuteTransaction(blockManager, "ResetDispute", opts, epoch) +} + +//This functiom gets Disputes mapping +func (blockManagerUtils BlockManagerUtils) Disputes(client *ethclient.Client, opts *bind.CallOpts, epoch uint32, address common.Address) (types.DisputesStruct, error) { + blockManager := utilsInterface.GetBlockManager(client) + returnedValues := utils.InvokeFunctionWithTimeout(blockManager, "Disputes", opts, epoch, address) + returnedError := utils.CheckIfAnyError(returnedValues) + if returnedError != nil { + return types.DisputesStruct{}, returnedError + } + disputesMapping := returnedValues[0].Interface().(struct { + LeafId uint16 + LastVisitedValue *big.Int + AccWeight *big.Int + Median *big.Int + }) + return disputesMapping, nil } //This function is used to reveal the values @@ -661,7 +732,7 @@ func (voteManagerUtils VoteManagerUtils) Reveal(client *ethclient.Client, opts * err error ) err = retry.Do(func() error { - txn, err = voteManager.Reveal(opts, epoch, tree, signature) + txn, err = ExecuteTransaction(voteManager, "Reveal", opts, epoch, tree, signature) if err != nil { log.Error("Error in revealing... Retrying") return err @@ -682,7 +753,7 @@ func (voteManagerUtils VoteManagerUtils) Commit(client *ethclient.Client, opts * err error ) err = retry.Do(func() error { - txn, err = voteManager.Commit(opts, epoch, commitment) + txn, err = ExecuteTransaction(voteManager, "Commit", opts, epoch, commitment) if err != nil { log.Error("Error in committing... Retrying") return err @@ -698,55 +769,65 @@ func (voteManagerUtils VoteManagerUtils) Commit(client *ethclient.Client, opts * //This function is used to check the allowance of staker func (tokenManagerUtils TokenManagerUtils) Allowance(client *ethclient.Client, opts *bind.CallOpts, owner common.Address, spender common.Address) (*big.Int, error) { tokenManager := utilsInterface.GetTokenManager(client) - return tokenManager.Allowance(opts, owner, spender) + returnedValues := utils.InvokeFunctionWithTimeout(tokenManager, "Allowance", opts, owner, spender) + returnedError := utils.CheckIfAnyError(returnedValues) + if returnedError != nil { + return nil, returnedError + } + return returnedValues[0].Interface().(*big.Int), nil } //This function is used to approve the transaction func (tokenManagerUtils TokenManagerUtils) Approve(client *ethclient.Client, opts *bind.TransactOpts, spender common.Address, amount *big.Int) (*Types.Transaction, error) { tokenManager := utilsInterface.GetTokenManager(client) - return tokenManager.Approve(opts, spender, amount) + return ExecuteTransaction(tokenManager, "Approve", opts, spender, amount) } //This function is used to transfer the tokens func (tokenManagerUtils TokenManagerUtils) Transfer(client *ethclient.Client, opts *bind.TransactOpts, recipient common.Address, amount *big.Int) (*Types.Transaction, error) { tokenManager := utilsInterface.GetTokenManager(client) - return tokenManager.Transfer(opts, recipient, amount) + return ExecuteTransaction(tokenManager, "Transfer", opts, recipient, amount) } //This function is used to create the job func (assetManagerUtils AssetManagerUtils) CreateJob(client *ethclient.Client, opts *bind.TransactOpts, weight uint8, power int8, selectorType uint8, name string, selector string, url string) (*Types.Transaction, error) { assetManager := utilsInterface.GetCollectionManager(client) - return assetManager.CreateJob(opts, weight, power, selectorType, name, selector, url) + return ExecuteTransaction(assetManager, "CreateJob", opts, weight, power, selectorType, name, selector, url) } //This function is used to set the collection status func (assetManagerUtils AssetManagerUtils) SetCollectionStatus(client *ethclient.Client, opts *bind.TransactOpts, assetStatus bool, id uint16) (*Types.Transaction, error) { assetManager := utilsInterface.GetCollectionManager(client) - return assetManager.SetCollectionStatus(opts, assetStatus, id) + return ExecuteTransaction(assetManager, "SetCollectionStatus", opts, assetStatus, id) } //This function is used to get the active status func (assetManagerUtils AssetManagerUtils) GetActiveStatus(client *ethclient.Client, opts *bind.CallOpts, id uint16) (bool, error) { assetMananger := utilsInterface.GetCollectionManager(client) - return assetMananger.GetCollectionStatus(opts, id) + returnedValues := utils.InvokeFunctionWithTimeout(assetMananger, "GetCollectionStatus", opts, id) + returnedError := utils.CheckIfAnyError(returnedValues) + if returnedError != nil { + return false, returnedError + } + return returnedValues[0].Interface().(bool), nil } //This function is used to update the job func (assetManagerUtils AssetManagerUtils) UpdateJob(client *ethclient.Client, opts *bind.TransactOpts, jobId uint16, weight uint8, power int8, selectorType uint8, selector string, url string) (*Types.Transaction, error) { assetManager := utilsInterface.GetCollectionManager(client) - return assetManager.UpdateJob(opts, jobId, weight, power, selectorType, selector, url) + return ExecuteTransaction(assetManager, "UpdateJob", opts, jobId, weight, power, selectorType, selector, url) } //This function is used to create the collection func (assetManagerUtils AssetManagerUtils) CreateCollection(client *ethclient.Client, opts *bind.TransactOpts, tolerance uint32, power int8, aggregationMethod uint32, jobIDs []uint16, name string) (*Types.Transaction, error) { assetManager := utilsInterface.GetCollectionManager(client) - return assetManager.CreateCollection(opts, tolerance, power, aggregationMethod, jobIDs, name) + return ExecuteTransaction(assetManager, "CreateCollection", opts, tolerance, power, aggregationMethod, jobIDs, name) } //This function is used to update the collection func (assetManagerUtils AssetManagerUtils) UpdateCollection(client *ethclient.Client, opts *bind.TransactOpts, collectionId uint16, tolerance uint32, aggregationMethod uint32, power int8, jobIds []uint16) (*Types.Transaction, error) { assetManager := utilsInterface.GetCollectionManager(client) - return assetManager.UpdateCollection(opts, collectionId, tolerance, aggregationMethod, power, jobIds) + return ExecuteTransaction(assetManager, "UpdateCollection", opts, collectionId, tolerance, aggregationMethod, power, jobIds) } //This function returns the provider in string @@ -779,6 +860,10 @@ func (flagSetUtils FLagSetUtils) GetStringLogLevel(flagSet *pflag.FlagSet) (stri return flagSet.GetString("logLevel") } +func (flagSetUtils FLagSetUtils) GetInt64RPCTimeout(flagSet *pflag.FlagSet) (int64, error) { + return flagSet.GetInt64("rpcTimeout") +} + //This function returns Gas Limit in Float32 func (flagSetUtils FLagSetUtils) GetFloat32GasLimit(flagSet *pflag.FlagSet) (float32, error) { return flagSet.GetFloat32("gasLimit") @@ -824,6 +909,11 @@ func (flagSetUtils FLagSetUtils) GetRootFloat32GasLimit() (float32, error) { return rootCmd.PersistentFlags().GetFloat32("gasLimit") } +//This function returns the gas limit of root in Float32 +func (flagSetUtils FLagSetUtils) GetRootInt64RPCTimeout() (int64, error) { + return rootCmd.PersistentFlags().GetInt64("rpcTimeout") +} + //This function returns the from in string func (flagSetUtils FLagSetUtils) GetStringFrom(flagSet *pflag.FlagSet) (string, error) { return flagSet.GetString("from") @@ -934,6 +1024,11 @@ func (flagSetUtils FLagSetUtils) GetStringSliceRogueMode(flagSet *pflag.FlagSet) return flagSet.GetStringSlice("rogueMode") } +//This function is used to check the inputs gor backupNode flag +func (flagSetUtils FLagSetUtils) GetStringSliceBackupNode(flagSet *pflag.FlagSet) ([]string, error) { + return flagSet.GetStringSlice("backupNode") +} + //This function is used to check if exposeMetrics is passed or not func (flagSetUtils FLagSetUtils) GetStringExposeMetrics(flagSet *pflag.FlagSet) (string, error) { return flagSet.GetString("exposeMetrics") @@ -967,8 +1062,8 @@ func (c CryptoUtils) HexToECDSA(hexKey string) (*ecdsa.PrivateKey, error) { } //This function is used to give the sorted Ids -func (*UtilsStruct) GiveSorted(client *ethclient.Client, blockManager *bindings.BlockManager, txnOpts *bind.TransactOpts, epoch uint32, assetId uint16, sortedStakers []*big.Int) { - GiveSorted(client, blockManager, txnOpts, epoch, assetId, sortedStakers) +func (*UtilsStruct) GiveSorted(client *ethclient.Client, blockManager *bindings.BlockManager, txnArgs types.TransactionOptions, epoch uint32, assetId uint16, sortedStakers []*big.Int) error { + return GiveSorted(client, blockManager, txnArgs, epoch, assetId, sortedStakers) } //This function is used to write config as diff --git a/cmd/transfer.go b/cmd/transfer.go index 5f46fb79..9cf56a05 100644 --- a/cmd/transfer.go +++ b/cmd/transfer.go @@ -2,13 +2,14 @@ package cmd import ( - "github.com/ethereum/go-ethereum/ethclient" "razor/core" "razor/core/types" "razor/logger" "razor/pkg/bindings" "razor/utils" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/spf13/pflag" "github.com/ethereum/go-ethereum/common" @@ -34,6 +35,7 @@ func initialiseTransfer(cmd *cobra.Command, args []string) { func (*UtilsStruct) ExecuteTransfer(flagSet *pflag.FlagSet) { config, err := cmdUtils.GetConfigData() utils.CheckError("Error in getting config: ", err) + log.Debugf("ExecuteTransfer: Config: %+v", config) client := razorUtils.ConnectToClient(config.Provider) @@ -41,9 +43,11 @@ func (*UtilsStruct) ExecuteTransfer(flagSet *pflag.FlagSet) { utils.CheckError("Error in getting fromAddress: ", err) logger.SetLoggerParameters(client, fromAddress) + log.Debug("Checking to assign log file...") razorUtils.AssignLogFile(flagSet) - password := razorUtils.AssignPassword() + log.Debug("Getting password...") + password := razorUtils.AssignPassword(flagSet) toAddress, err := flagSetUtils.GetStringTo(flagSet) utils.CheckError("Error in getting toAddress: ", err) @@ -51,6 +55,7 @@ func (*UtilsStruct) ExecuteTransfer(flagSet *pflag.FlagSet) { balance, err := razorUtils.FetchBalance(client, fromAddress) utils.CheckError("Error in fetching razor balance: ", err) + log.Debug("Getting amount in wei...") valueInWei, err := cmdUtils.AssignAmountInWei(flagSet) utils.CheckError("Error in getting amount: ", err) @@ -62,6 +67,7 @@ func (*UtilsStruct) ExecuteTransfer(flagSet *pflag.FlagSet) { Balance: balance, } + log.Debugf("Calling Transfer() with arguments transferInput = %+v", transferInput) txn, err := cmdUtils.Transfer(client, config, transferInput) utils.CheckError("Transfer error: ", err) log.Info("Transaction Hash: ", txn) @@ -71,7 +77,7 @@ func (*UtilsStruct) ExecuteTransfer(flagSet *pflag.FlagSet) { //This function transfers the razors from your account to others account func (*UtilsStruct) Transfer(client *ethclient.Client, config types.Configurations, transferInput types.TransferInput) (common.Hash, error) { - + log.Debug("Checking for sufficient balance...") razorUtils.CheckAmountAndBalance(transferInput.ValueInWei, transferInput.Balance) txnOpts := razorUtils.GetTxnOpts(types.TransactionOptions{ @@ -87,6 +93,7 @@ func (*UtilsStruct) Transfer(client *ethclient.Client, config types.Configuratio }) log.Infof("Transferring %g tokens from %s to %s", razorUtils.GetAmountInDecimal(transferInput.ValueInWei), transferInput.FromAddress, transferInput.ToAddress) + log.Debugf("Executing Transfer transaction with toAddress: %s, amount: %s", transferInput.ToAddress, transferInput.ValueInWei) txn, err := tokenManagerUtils.Transfer(client, txnOpts, common.HexToAddress(transferInput.ToAddress), transferInput.ValueInWei) if err != nil { log.Errorf("Error in transferring tokens ") @@ -102,12 +109,14 @@ func init() { Amount string From string To string + Password string WeiRazor bool ) transferCmd.Flags().StringVarP(&Amount, "value", "v", "0", "value to transfer") transferCmd.Flags().StringVarP(&From, "from", "", "", "transfer from") transferCmd.Flags().StringVarP(&To, "to", "", "", "transfer to") + transferCmd.Flags().StringVarP(&Password, "password", "", "", "password path to protect the keystore") transferCmd.Flags().BoolVarP(&WeiRazor, "weiRazor", "", false, "value can be passed in wei") amountErr := transferCmd.MarkFlagRequired("value") diff --git a/cmd/transfer_test.go b/cmd/transfer_test.go index b6f00c9d..968b3896 100644 --- a/cmd/transfer_test.go +++ b/cmd/transfer_test.go @@ -267,7 +267,7 @@ func TestExecuteTransfer(t *testing.T) { utilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet")) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) - utilsMock.On("AssignPassword").Return(tt.args.password) + utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) flagsetUtilsMock.On("GetStringFrom", flagSet).Return(tt.args.from, tt.args.fromErr) flagsetUtilsMock.On("GetStringTo", flagSet).Return(tt.args.to, tt.args.toErr) cmdUtilsMock.On("AssignAmountInWei", flagSet).Return(tt.args.amount, tt.args.amountErr) diff --git a/cmd/unlockWithdraw.go b/cmd/unlockWithdraw.go index ec232b84..d42b9352 100644 --- a/cmd/unlockWithdraw.go +++ b/cmd/unlockWithdraw.go @@ -3,17 +3,18 @@ package cmd import ( "errors" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/spf13/cobra" - "github.com/spf13/pflag" "math/big" "razor/core" "razor/core/types" "razor/logger" "razor/pkg/bindings" "razor/utils" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/spf13/cobra" + "github.com/spf13/pflag" ) // unlockWithdrawCmd represents the unlockWithdraw command @@ -33,22 +34,28 @@ func initializeUnlockWithdraw(cmd *cobra.Command, args []string) { func (*UtilsStruct) ExecuteUnlockWithdraw(flagSet *pflag.FlagSet) { config, err := cmdUtils.GetConfigData() utils.CheckError("Error in getting config: ", err) + log.Debugf("ExecuteUnlockWithdraw: Config: %+v", config) client := razorUtils.ConnectToClient(config.Provider) address, err := flagSetUtils.GetStringAddress(flagSet) utils.CheckError("Error in getting address: ", err) + log.Debug("ExecuteUnlockWithdraw: Address: ", address) logger.SetLoggerParameters(client, address) + log.Debug("Checking to assign log file...") razorUtils.AssignLogFile(flagSet) - password := razorUtils.AssignPassword() + log.Debug("Getting password...") + password := razorUtils.AssignPassword(flagSet) razorUtils.CheckEthBalanceIsZero(client, address) stakerId, err := razorUtils.AssignStakerId(flagSet, client, address) utils.CheckError("Error in fetching stakerId: ", err) + log.Debug("ExecuteUnlockWithdraw: StakerId: ", stakerId) + log.Debugf("ExecuteUnlockWithdraw: Calling HandleWithdrawLock with arguments account address = %s, stakerId = %d", address, stakerId) txn, err := cmdUtils.HandleWithdrawLock(client, types.Account{ Address: address, Password: password, @@ -67,6 +74,7 @@ func (*UtilsStruct) HandleWithdrawLock(client *ethclient.Client, account types.A if err != nil { return core.NilHash, err } + log.Debugf("HandleWithdrawLock: Withdraw lock: %+v", withdrawLock) if withdrawLock.UnlockAfter.Cmp(big.NewInt(0)) == 0 { log.Error("initiateWithdrawCmd command not called before unlocking razors!") @@ -78,6 +86,7 @@ func (*UtilsStruct) HandleWithdrawLock(client *ethclient.Client, account types.A log.Error("Error in fetching epoch") return core.NilHash, err } + log.Debug("HandleWithdrawLock: Epoch: ", epoch) if big.NewInt(int64(epoch)).Cmp(withdrawLock.UnlockAfter) >= 0 { txnArgs := types.TransactionOptions{ @@ -92,6 +101,7 @@ func (*UtilsStruct) HandleWithdrawLock(client *ethclient.Client, account types.A Parameters: []interface{}{stakerId}, } txnOpts := razorUtils.GetTxnOpts(txnArgs) + log.Debug("HandleWithdrawLock: Calling UnlockWithdraw() with arguments stakerId = ", stakerId) return cmdUtils.UnlockWithdraw(client, txnOpts, stakerId) } return core.NilHash, errors.New("withdrawLock period not over yet! Please try after some time") @@ -101,6 +111,7 @@ func (*UtilsStruct) HandleWithdrawLock(client *ethclient.Client, account types.A func (*UtilsStruct) UnlockWithdraw(client *ethclient.Client, txnOpts *bind.TransactOpts, stakerId uint32) (common.Hash, error) { log.Info("Unlocking funds...") + log.Debug("Executing UnlockWithdraw transaction with stakerId = ", stakerId) txn, err := stakeManagerUtils.UnlockWithdraw(client, txnOpts, stakerId) if err != nil { log.Error("Error in unlocking funds") @@ -116,10 +127,12 @@ func init() { rootCmd.AddCommand(unlockWithdrawCmd) var ( Address string + Password string StakerId uint32 ) unlockWithdrawCmd.Flags().StringVarP(&Address, "address", "a", "", "address of the user") + unlockWithdrawCmd.Flags().StringVarP(&Password, "password", "", "", "password path of user to protect the keystore") unlockWithdrawCmd.Flags().Uint32VarP(&StakerId, "stakerId", "", 0, "password path of user to protect the keystore") addrErr := unlockWithdrawCmd.MarkFlagRequired("address") diff --git a/cmd/unlockWithdraw_test.go b/cmd/unlockWithdraw_test.go index 87b6c36a..3d45424f 100644 --- a/cmd/unlockWithdraw_test.go +++ b/cmd/unlockWithdraw_test.go @@ -109,7 +109,7 @@ func TestExecuteUnlockWithdraw(t *testing.T) { utilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet")) flagSetUtilsMock.On("GetStringAddress", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.address, tt.args.addressErr) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) - utilsMock.On("AssignPassword").Return(tt.args.password) + utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) utilsMock.On("ConnectToClient", mock.AnythingOfType("string")).Return(client) utilsMock.On("CheckEthBalanceIsZero", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return() utilsMock.On("AssignStakerId", mock.Anything, mock.Anything, mock.Anything).Return(tt.args.stakerId, tt.args.stakerIdErr) diff --git a/cmd/unstake.go b/cmd/unstake.go index 6ce69fc2..06d52379 100644 --- a/cmd/unstake.go +++ b/cmd/unstake.go @@ -3,7 +3,6 @@ package cmd import ( "errors" - "github.com/ethereum/go-ethereum/common" "math/big" "razor/core" "razor/core/types" @@ -11,6 +10,8 @@ import ( "razor/pkg/bindings" "razor/utils" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" "github.com/spf13/pflag" @@ -37,6 +38,7 @@ func initialiseUnstake(cmd *cobra.Command, args []string) { func (*UtilsStruct) ExecuteUnstake(flagSet *pflag.FlagSet) { config, err := cmdUtils.GetConfigData() utils.CheckError("Error in getting config: ", err) + log.Debugf("ExecuteUnstake: Config: %+v", config) client := razorUtils.ConnectToClient(config.Provider) @@ -44,10 +46,13 @@ func (*UtilsStruct) ExecuteUnstake(flagSet *pflag.FlagSet) { utils.CheckError("Error in getting address: ", err) logger.SetLoggerParameters(client, address) + log.Debug("Checking to assign log file...") razorUtils.AssignLogFile(flagSet) - password := razorUtils.AssignPassword() + log.Debug("Getting password...") + password := razorUtils.AssignPassword(flagSet) + log.Debug("Getting amount in wei...") valueInWei, err := cmdUtils.AssignAmountInWei(flagSet) utils.CheckError("Error in getting amountInWei: ", err) @@ -63,6 +68,7 @@ func (*UtilsStruct) ExecuteUnstake(flagSet *pflag.FlagSet) { StakerId: stakerId, } + log.Debugf("ExecuteUnstake: Calling Unstake() with arguments unstakeInput: %+v", unstakeInput) txnHash, err := cmdUtils.Unstake(config, client, unstakeInput) utils.CheckError("Unstake Error: ", err) if txnHash != core.NilHash { @@ -87,6 +93,8 @@ func (*UtilsStruct) Unstake(config types.Configurations, client *ethclient.Clien log.Error("Error in getting staker: ", err) return core.NilHash, err } + log.Debugf("Unstake: Staker info: %+v", staker) + log.Debug("Unstake: Calling ApproveUnstake()...") approveHash, err := cmdUtils.ApproveUnstake(client, staker, txnArgs) if err != nil { return core.NilHash, err @@ -110,6 +118,7 @@ func (*UtilsStruct) Unstake(config types.Configurations, client *ethclient.Clien log.Error("Error in getting unstakeLock: ", err) return core.NilHash, err } + log.Debugf("Unstake: Unstake lock: %+v", unstakeLock) if unstakeLock.Amount.Cmp(big.NewInt(0)) != 0 { err := errors.New("existing unstake lock") @@ -120,6 +129,7 @@ func (*UtilsStruct) Unstake(config types.Configurations, client *ethclient.Clien txnArgs.Parameters = []interface{}{stakerId, txnArgs.Amount} txnOpts := razorUtils.GetTxnOpts(txnArgs) log.Info("Unstaking coins") + log.Debugf("Executing Unstake transaction with stakerId = %d, amount = %s", stakerId, txnArgs.Amount) txn, err := stakeManagerUtils.Unstake(txnArgs.Client, txnOpts, stakerId, txnArgs.Amount) if err != nil { log.Error("Error in un-staking: ", err) @@ -148,12 +158,14 @@ func init() { var ( Address string AmountToUnStake string + Password string WeiRazor bool StakerId uint32 ) unstakeCmd.Flags().StringVarP(&Address, "address", "a", "", "user's address") unstakeCmd.Flags().StringVarP(&AmountToUnStake, "value", "v", "0", "value of sRazors to un-stake") + unstakeCmd.Flags().StringVarP(&Password, "password", "", "", "password path to protect the keystore") unstakeCmd.Flags().BoolVarP(&WeiRazor, "weiRazor", "", false, "value can be passed in wei") unstakeCmd.Flags().Uint32VarP(&StakerId, "stakerId", "", 0, "staker id") diff --git a/cmd/unstake_test.go b/cmd/unstake_test.go index 053db6db..c594cc62 100644 --- a/cmd/unstake_test.go +++ b/cmd/unstake_test.go @@ -317,7 +317,7 @@ func TestExecuteUnstake(t *testing.T) { utilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet")) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) - utilsMock.On("AssignPassword").Return(tt.args.password) + utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) flagSetUtilsMock.On("GetStringAddress", flagSet).Return(tt.args.address, tt.args.addressErr) utilsMock.On("ConnectToClient", mock.AnythingOfType("string")).Return(client) cmdUtilsMock.On("AssignAmountInWei", flagSet).Return(tt.args.value, tt.args.valueErr) diff --git a/cmd/updateCollection.go b/cmd/updateCollection.go index 48293151..0066283c 100644 --- a/cmd/updateCollection.go +++ b/cmd/updateCollection.go @@ -2,15 +2,16 @@ package cmd import ( - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/spf13/cobra" - "github.com/spf13/pflag" "razor/core" "razor/core/types" "razor/logger" "razor/pkg/bindings" "razor/utils" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/spf13/cobra" + "github.com/spf13/pflag" ) var updateCollectionCmd = &cobra.Command{ @@ -36,6 +37,7 @@ func initialiseUpdateCollection(cmd *cobra.Command, args []string) { func (*UtilsStruct) ExecuteUpdateCollection(flagSet *pflag.FlagSet) { config, err := cmdUtils.GetConfigData() utils.CheckError("Error in getting config: ", err) + log.Debugf("ExecuteUpdateCollection: Config : %+v", config) client := razorUtils.ConnectToClient(config.Provider) @@ -43,9 +45,11 @@ func (*UtilsStruct) ExecuteUpdateCollection(flagSet *pflag.FlagSet) { utils.CheckError("Error in getting address: ", err) logger.SetLoggerParameters(client, address) + log.Debug("Checking to assign log file...") razorUtils.AssignLogFile(flagSet) - password := razorUtils.AssignPassword() + log.Debug("Getting password...") + password := razorUtils.AssignPassword(flagSet) collectionId, err := flagSetUtils.GetUint16CollectionId(flagSet) utils.CheckError("Error in getting collectionID: ", err) @@ -70,6 +74,7 @@ func (*UtilsStruct) ExecuteUpdateCollection(flagSet *pflag.FlagSet) { JobIds: jobIdInUint, Tolerance: tolerance, } + log.Debugf("ExecuteUpdateCollection: Calling UpdateCollection() with arguments collectionInput: %+v, collectionId: %d", collectionInput, collectionId) txn, err := cmdUtils.UpdateCollection(client, config, collectionInput, collectionId) utils.CheckError("Update Collection error: ", err) err = razorUtils.WaitForBlockCompletion(client, txn.String()) @@ -79,6 +84,7 @@ func (*UtilsStruct) ExecuteUpdateCollection(flagSet *pflag.FlagSet) { //This function allows the admin to update an existing collection func (*UtilsStruct) UpdateCollection(client *ethclient.Client, config types.Configurations, collectionInput types.CreateCollectionInput, collectionId uint16) (common.Hash, error) { jobIds := razorUtils.ConvertUintArrayToUint16Array(collectionInput.JobIds) + log.Debug("UpdateCollection: Uint16 jobIds: ", jobIds) _, err := cmdUtils.WaitIfCommitState(client, "update collection") if err != nil { log.Error("Error in fetching state") @@ -95,6 +101,7 @@ func (*UtilsStruct) UpdateCollection(client *ethclient.Client, config types.Conf Parameters: []interface{}{collectionId, collectionInput.Tolerance, collectionInput.Aggregation, collectionInput.Power, jobIds}, ABI: bindings.CollectionManagerABI, }) + log.Debugf("Executing UpdateCollection transaction with collectionId = %d, tolerance = %d, aggregation method = %d, power = %d, jobIds = %v", collectionId, collectionInput.Tolerance, collectionInput.Aggregation, collectionInput.Power, jobIds) txn, err := assetManagerUtils.UpdateCollection(client, txnOpts, collectionId, collectionInput.Tolerance, collectionInput.Aggregation, collectionInput.Power, jobIds) if err != nil { log.Error("Error in updating collection") @@ -112,6 +119,7 @@ func init() { Account string CollectionId uint16 AggregationMethod uint32 + Password string Power int8 JobIds []uint Tolerance uint16 @@ -121,6 +129,7 @@ func init() { updateCollectionCmd.Flags().Uint16VarP(&CollectionId, "collectionId", "", 0, "collection id to be modified") updateCollectionCmd.Flags().Uint32VarP(&AggregationMethod, "aggregation", "", 1, "aggregation method to be used") updateCollectionCmd.Flags().Int8VarP(&Power, "power", "", 0, "multiplier for the collection") + updateCollectionCmd.Flags().StringVarP(&Password, "password", "", "", "password path of job creator to protect the keystore") updateCollectionCmd.Flags().UintSliceVarP(&JobIds, "jobIds", "", []uint{}, "job ids for the collection") updateCollectionCmd.Flags().Uint16VarP(&Tolerance, "tolerance", "", 0, "tolerance") diff --git a/cmd/updateCollection_test.go b/cmd/updateCollection_test.go index 31a420fb..a3d0b724 100644 --- a/cmd/updateCollection_test.go +++ b/cmd/updateCollection_test.go @@ -302,7 +302,7 @@ func TestExecuteUpdateCollection(t *testing.T) { utilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet")) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) - utilsMock.On("AssignPassword").Return(tt.args.password) + utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) flagsetUtilsMock.On("GetStringAddress", flagSet).Return(tt.args.address, tt.args.addressErr) flagsetUtilsMock.On("GetUint16CollectionId", flagSet).Return(tt.args.collectionId, tt.args.collectionIdErr) flagsetUtilsMock.On("GetUintSliceJobIds", flagSet).Return(tt.args.jobId, tt.args.jobIdErr) diff --git a/cmd/updateCommission.go b/cmd/updateCommission.go index 9f68c882..ec8a6af3 100644 --- a/cmd/updateCommission.go +++ b/cmd/updateCommission.go @@ -3,14 +3,15 @@ package cmd import ( "errors" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/spf13/pflag" "razor/core" "razor/core/types" "razor/logger" "razor/pkg/bindings" "razor/utils" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/spf13/pflag" + "github.com/spf13/cobra" ) @@ -33,6 +34,7 @@ func initialiseUpdateCommission(cmd *cobra.Command, args []string) { func (*UtilsStruct) ExecuteUpdateCommission(flagSet *pflag.FlagSet) { config, err := cmdUtils.GetConfigData() utils.CheckError("Error in getting config: ", err) + log.Debugf("ExecuteUpdateCommission: Config: %+v", config) client := razorUtils.ConnectToClient(config.Provider) @@ -40,9 +42,11 @@ func (*UtilsStruct) ExecuteUpdateCommission(flagSet *pflag.FlagSet) { utils.CheckError("Error in getting address: ", err) logger.SetLoggerParameters(client, address) + log.Debug("Checking to assign log file...") razorUtils.AssignLogFile(flagSet) - password := razorUtils.AssignPassword() + log.Debug("Getting password...") + password := razorUtils.AssignPassword(flagSet) commission, err := flagSetUtils.GetUint8Commission(flagSet) utils.CheckError("Error in getting commission", err) @@ -50,12 +54,15 @@ func (*UtilsStruct) ExecuteUpdateCommission(flagSet *pflag.FlagSet) { stakerId, err := razorUtils.GetStakerId(client, address) utils.CheckError("Error in getting stakerId", err) - err = cmdUtils.UpdateCommission(config, client, types.UpdateCommissionInput{ + updateCommissionInput := types.UpdateCommissionInput{ Commission: commission, Address: address, Password: password, StakerId: stakerId, - }) + } + + log.Debugf("ExecuteUpdateCommission: calling UpdateCommission() with argument UpdateCommissionInput: %+v", updateCommissionInput) + err = cmdUtils.UpdateCommission(config, client, updateCommissionInput) utils.CheckError("SetDelegation error: ", err) } @@ -66,11 +73,13 @@ func (*UtilsStruct) UpdateCommission(config types.Configurations, client *ethcli log.Error("Error in fetching staker info") return err } + log.Debugf("UpdateCommission: Staker Info: %+v", stakerInfo) maxCommission, err := razorUtils.GetMaxCommission(client) if err != nil { return err } + log.Debug("UpdateCommission: Maximum Commission: ", maxCommission) if updateCommissionInput.Commission == 0 || updateCommissionInput.Commission > maxCommission { return errors.New("commission out of range") @@ -80,11 +89,13 @@ func (*UtilsStruct) UpdateCommission(config types.Configurations, client *ethcli if err != nil { return err } + log.Debug("UpdateCommission: Epoch limit to update commission: ", epochLimitForUpdateCommission) epoch, err := razorUtils.GetEpoch(client) if err != nil { return err } + log.Debug("UpdateCommission: Current epoch: ", epoch) if stakerInfo.EpochCommissionLastUpdated != 0 && (stakerInfo.EpochCommissionLastUpdated+uint32(epochLimitForUpdateCommission)) >= epoch { waitFor := uint32(epochLimitForUpdateCommission) - (epoch - stakerInfo.EpochCommissionLastUpdated) + 1 @@ -110,6 +121,7 @@ func (*UtilsStruct) UpdateCommission(config types.Configurations, client *ethcli } updateCommissionTxnOpts := razorUtils.GetTxnOpts(txnOpts) log.Infof("Setting the commission value of Staker %d to %d%%", updateCommissionInput.StakerId, updateCommissionInput.Commission) + log.Debug("Executing UpdateCommission transaction with commission = ", updateCommissionInput.Commission) txn, err := stakeManagerUtils.UpdateCommission(client, updateCommissionTxnOpts, updateCommissionInput.Commission) if err != nil { log.Error("Error in setting commission") @@ -129,12 +141,14 @@ func init() { var ( Address string Commission uint8 + Password string ) rootCmd.AddCommand(updateCommissionCmd) updateCommissionCmd.Flags().StringVarP(&Address, "address", "a", "", "your account address") updateCommissionCmd.Flags().Uint8VarP(&Commission, "commission", "c", 0, "commission") + updateCommissionCmd.Flags().StringVarP(&Password, "password", "", "", "password path to protect the keystore") addrErr := updateCommissionCmd.MarkFlagRequired("address") utils.CheckError("Address error: ", addrErr) diff --git a/cmd/updateCommission_test.go b/cmd/updateCommission_test.go index 2f126ed8..c9095feb 100644 --- a/cmd/updateCommission_test.go +++ b/cmd/updateCommission_test.go @@ -356,7 +356,7 @@ func TestExecuteUpdateCommission(t *testing.T) { utilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet")) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) flagsetUtilsMock.On("GetStringAddress", flagSet).Return(tt.args.address, tt.args.addressErr) - utilsMock.On("AssignPassword").Return(tt.args.password) + utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) flagsetUtilsMock.On("GetUint8Commission", flagSet).Return(tt.args.commission, tt.args.commissionErr) utilsMock.On("GetStakerId", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return(tt.args.stakerId, tt.args.stakerIdErr) utilsMock.On("ConnectToClient", mock.AnythingOfType("string")).Return(client) diff --git a/cmd/updateJob.go b/cmd/updateJob.go index 0cf2b2d4..cf858abc 100644 --- a/cmd/updateJob.go +++ b/cmd/updateJob.go @@ -2,15 +2,16 @@ package cmd import ( - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/spf13/cobra" - "github.com/spf13/pflag" "razor/core" "razor/core/types" "razor/logger" "razor/pkg/bindings" "razor/utils" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/spf13/cobra" + "github.com/spf13/pflag" ) var updateJobCmd = &cobra.Command{ @@ -36,6 +37,7 @@ func initialiseUpdateJob(cmd *cobra.Command, args []string) { func (*UtilsStruct) ExecuteUpdateJob(flagSet *pflag.FlagSet) { config, err := cmdUtils.GetConfigData() utils.CheckError("Error in getting config: ", err) + log.Debugf("ExecuteUpdateJob: Config: %+v", config) client := razorUtils.ConnectToClient(config.Provider) @@ -43,9 +45,11 @@ func (*UtilsStruct) ExecuteUpdateJob(flagSet *pflag.FlagSet) { utils.CheckError("Error in getting address: ", err) logger.SetLoggerParameters(client, address) + log.Debug("Checking to assign log file...") razorUtils.AssignLogFile(flagSet) - password := razorUtils.AssignPassword() + log.Debug("Getting password...") + password := razorUtils.AssignPassword(flagSet) jobId, err := flagSetUtils.GetUint16JobId(flagSet) utils.CheckError("Error in getting jobId: ", err) @@ -75,6 +79,7 @@ func (*UtilsStruct) ExecuteUpdateJob(flagSet *pflag.FlagSet) { SelectorType: selectorType, } + log.Debugf("ExecuteUpdateJob: Calling UpdateJob() with arguments jobInput = %+v, jobId = %d", jobInput, jobId) txn, err := cmdUtils.UpdateJob(client, config, jobInput, jobId) utils.CheckError("UpdateJob error: ", err) err = razorUtils.WaitForBlockCompletion(client, txn.String()) @@ -83,7 +88,6 @@ func (*UtilsStruct) ExecuteUpdateJob(flagSet *pflag.FlagSet) { //This function allows the admin to update an existing job func (*UtilsStruct) UpdateJob(client *ethclient.Client, config types.Configurations, jobInput types.CreateJobInput, jobId uint16) (common.Hash, error) { - _, err := cmdUtils.WaitIfCommitState(client, "update job") if err != nil { log.Error("Error in fetching state") @@ -100,6 +104,7 @@ func (*UtilsStruct) UpdateJob(client *ethclient.Client, config types.Configurati Parameters: []interface{}{jobId, jobInput.Weight, jobInput.Power, jobInput.SelectorType, jobInput.Selector, jobInput.Url}, ABI: bindings.CollectionManagerABI, }) + log.Debugf("Executing UpdateJob transaction with arguments jobId = %d, weight = %d, power = %d, selector type = %d, selector = %s, URL = %s", jobId, jobInput.Weight, jobInput.Power, jobInput.SelectorType, jobInput.Selector, jobInput.Url) txn, err := assetManagerUtils.UpdateJob(client, txnArgs, jobId, jobInput.Weight, jobInput.Power, jobInput.SelectorType, jobInput.Selector, jobInput.Url) if err != nil { return core.NilHash, err @@ -118,6 +123,7 @@ func init() { Power int8 Weight uint8 Account string + Password string ) updateJobCmd.Flags().Uint16VarP(&JobId, "jobId", "", 0, "job id") @@ -127,6 +133,7 @@ func init() { updateJobCmd.Flags().Int8VarP(&Power, "power", "", 0, "power") updateJobCmd.Flags().Uint8VarP(&Weight, "weight", "", 0, "weight") updateJobCmd.Flags().StringVarP(&Account, "address", "a", "", "address of the job creator") + updateJobCmd.Flags().StringVarP(&Password, "password", "", "", "password path of job creator to protect the keystore") jobIdErr := updateJobCmd.MarkFlagRequired("jobId") utils.CheckError("Job Id error: ", jobIdErr) diff --git a/cmd/updateJob_test.go b/cmd/updateJob_test.go index df6c7332..7292bcae 100644 --- a/cmd/updateJob_test.go +++ b/cmd/updateJob_test.go @@ -348,7 +348,7 @@ func TestExecuteUpdateJob(t *testing.T) { utilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet")) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) - utilsMock.On("AssignPassword").Return(tt.args.password) + utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) flagsetUtilsMock.On("GetStringAddress", flagSet).Return(tt.args.address, tt.args.addressErr) flagsetUtilsMock.On("GetStringUrl", flagSet).Return(tt.args.url, tt.args.urlErr) flagsetUtilsMock.On("GetStringSelector", flagSet).Return(tt.args.selector, tt.args.selectorErr) diff --git a/cmd/vote.go b/cmd/vote.go index ac46c6a6..778c59f7 100644 --- a/cmd/vote.go +++ b/cmd/vote.go @@ -6,7 +6,6 @@ import ( "encoding/hex" "errors" "fmt" - "github.com/ethereum/go-ethereum/crypto" "math/big" "os" "os/signal" @@ -17,12 +16,12 @@ import ( "razor/logger" "razor/pkg/bindings" "razor/utils" - "strings" "time" + "github.com/ethereum/go-ethereum/crypto" + "github.com/spf13/pflag" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" solsha3 "github.com/miguelmota/go-solidity-sha3" @@ -48,34 +47,48 @@ func initializeVote(cmd *cobra.Command, args []string) { func (*UtilsStruct) ExecuteVote(flagSet *pflag.FlagSet) { config, err := cmdUtils.GetConfigData() utils.CheckError("Error in getting config: ", err) + log.Debugf("ExecuteVote: Config: %+v", config) client := razorUtils.ConnectToClient(config.Provider) address, err := flagSetUtils.GetStringAddress(flagSet) utils.CheckError("Error in getting address: ", err) + log.Debug("ExecuteVote: Address: ", address) logger.SetLoggerParameters(client, address) + log.Debug("Checking to assign log file...") razorUtils.AssignLogFile(flagSet) - password := razorUtils.AssignPassword() + log.Debug("Getting password...") + password := razorUtils.AssignPassword(flagSet) isRogue, err := flagSetUtils.GetBoolRogue(flagSet) utils.CheckError("Error in getting rogue status: ", err) + log.Debug("ExecuteVote: IsRogue: ", isRogue) rogueMode, err := flagSetUtils.GetStringSliceRogueMode(flagSet) utils.CheckError("Error in getting rogue modes: ", err) + log.Debug("ExecuteVote: RogueMode: ", rogueMode) + + backupNodeActionsToIgnore, err := flagSetUtils.GetStringSliceBackupNode(flagSet) + utils.CheckError("Error in getting backupNode actions to ignore: ", err) + log.Debug("ExecuteVote: Backup node actions to ignore: ", backupNodeActionsToIgnore) rogueData := types.Rogue{ IsRogue: isRogue, RogueMode: rogueMode, } + if rogueData.IsRogue { + log.Warn("YOU ARE RUNNING VOTE IN ROGUE MODE, THIS CAN INCUR PENALTIES!") + } + account := types.Account{Address: address, Password: password} cmdUtils.HandleExit() - - if err := cmdUtils.Vote(context.Background(), config, client, rogueData, account); err != nil { - log.Errorf("%s\n", err) + log.Debugf("Calling Vote() with arguments rogueData = %+v, account address = %s, backup node actions to ignore = %s", rogueData, account.Address, backupNodeActionsToIgnore) + if err := cmdUtils.Vote(context.Background(), config, client, rogueData, account, backupNodeActionsToIgnore); err != nil { + log.Errorf("%v\n", err) osUtils.Exit(1) } } @@ -105,7 +118,7 @@ func (*UtilsStruct) HandleExit() { } //This function handles all the states of voting -func (*UtilsStruct) Vote(ctx context.Context, config types.Configurations, client *ethclient.Client, rogueData types.Rogue, account types.Account) error { +func (*UtilsStruct) Vote(ctx context.Context, config types.Configurations, client *ethclient.Client, rogueData types.Rogue, account types.Account, backupNodeActionsToIgnore []string) error { header, err := utils.UtilsInterface.GetLatestBlockWithRetry(client) utils.CheckError("Error in getting block: ", err) for { @@ -113,28 +126,30 @@ func (*UtilsStruct) Vote(ctx context.Context, config types.Configurations, clien case <-ctx.Done(): return nil default: + log.Debugf("Vote: Header value: %d", header.Number) latestHeader, err := utils.UtilsInterface.GetLatestBlockWithRetry(client) if err != nil { log.Error("Error in fetching block: ", err) continue } + log.Debugf("Vote: Latest header value: %d", latestHeader.Number) if latestHeader.Number.Cmp(header.Number) != 0 { header = latestHeader - cmdUtils.HandleBlock(client, account, latestHeader.Number, config, rogueData) + cmdUtils.HandleBlock(client, account, latestHeader.Number, config, rogueData, backupNodeActionsToIgnore) } } } } var ( - _commitData types.CommitData - lastVerification uint32 - blockConfirmed uint32 - disputeData types.DisputeFileData + globalCommitDataStruct types.CommitFileData + lastVerification uint32 + blockConfirmed uint32 + disputeData types.DisputeFileData ) //This function handles the block -func (*UtilsStruct) HandleBlock(client *ethclient.Client, account types.Account, blockNumber *big.Int, config types.Configurations, rogueData types.Rogue) { +func (*UtilsStruct) HandleBlock(client *ethclient.Client, account types.Account, blockNumber *big.Int, config types.Configurations, rogueData types.Rogue, backupNodeActionsToIgnore []string) { state, err := razorUtils.GetDelayedState(client, config.BufferPercent) if err != nil { log.Error("Error in getting state: ", err) @@ -164,7 +179,7 @@ func (*UtilsStruct) HandleBlock(client *ethclient.Client, account types.Account, ethBalance, err := utils.UtilsInterface.BalanceAtWithRetry(client, common.HexToAddress(account.Address)) if err != nil { - log.Errorf("Error in fetching balance of the account: %s\n%s", account.Address, err) + log.Errorf("Error in fetching balance of the account: %s\n%v", account.Address, err) return } actualStake, err := razorUtils.ConvertWeiToEth(stakedAmount) @@ -204,29 +219,35 @@ func (*UtilsStruct) HandleBlock(client *ethclient.Client, account types.Account, switch state { case 0: + log.Debugf("Starting commit...") err := cmdUtils.InitiateCommit(client, config, account, epoch, stakerId, rogueData) if err != nil { log.Error(err) break } case 1: + log.Debugf("Starting reveal...") err := cmdUtils.InitiateReveal(client, config, account, epoch, staker, rogueData) if err != nil { log.Error(err) break } case 2: + log.Debugf("Starting propose...") err := cmdUtils.InitiatePropose(client, config, account, epoch, staker, blockNumber, rogueData) if err != nil { log.Error(err) break } case 3: + log.Debugf("Last verification: %d", lastVerification) if lastVerification >= epoch { + log.Debugf("Last verification (%d) is greater or equal to current epoch (%d)", lastVerification, epoch) + log.Debugf("Won't dispute now") break } - err := cmdUtils.HandleDispute(client, config, account, epoch, blockNumber, rogueData) + err := cmdUtils.HandleDispute(client, config, account, epoch, blockNumber, rogueData, backupNodeActionsToIgnore) if err != nil { log.Error(err) break @@ -235,6 +256,7 @@ func (*UtilsStruct) HandleBlock(client *ethclient.Client, account types.Account, lastVerification = epoch if utilsInterface.IsFlagPassed("autoClaimBounty") { + log.Debugf("Automatically claiming bounty") err = cmdUtils.HandleClaimBounty(client, config, account) if err != nil { log.Error(err) @@ -243,6 +265,8 @@ func (*UtilsStruct) HandleBlock(client *ethclient.Client, account types.Account, } case 4: + log.Debugf("Last verification: %d", lastVerification) + log.Debugf("Block confirmed: %d", blockConfirmed) if lastVerification == epoch && blockConfirmed < epoch { txn, err := cmdUtils.ClaimBlockReward(types.TransactionOptions{ Client: client, @@ -285,20 +309,25 @@ func (*UtilsStruct) InitiateCommit(client *ethclient.Client, config types.Config log.Error(err) return err } + log.Debug("InitiateCommit: Staker:", staker) stakedAmount := staker.Stake minStakeAmount, err := utils.UtilsInterface.GetMinStakeAmount(client) if err != nil { log.Error("Error in getting minimum stake amount: ", err) return err } + log.Debug("InitiateCommit: Minimum stake amount: ", minStakeAmount) if stakedAmount.Cmp(minStakeAmount) < 0 { log.Error("Stake is below minimum required. Kindly add stake to continue voting.") return nil } + lastCommit, err := razorUtils.GetEpochLastCommitted(client, stakerId) if err != nil { return errors.New("Error in fetching last commit: " + err.Error()) } + log.Debug("InitiateCommit: Epoch last committed: ", lastCommit) + if lastCommit >= epoch { log.Debugf("Cannot commit in epoch %d because last committed epoch is %d", epoch, lastCommit) return nil @@ -307,45 +336,57 @@ func (*UtilsStruct) InitiateCommit(client *ethclient.Client, config types.Config if err != nil { return err } + log.Debugf("InitiateCommit: .razor directory path: %s", razorPath) keystorePath := path.Join(razorPath, "keystore_files") - + log.Debugf("InitiateCommit: Keystore file path: %s", keystorePath) + log.Debugf("InitiateCommit: Calling CalculateSecret() with arguments epoch = %d, keystorePath = %s, chainId = %s", epoch, keystorePath, core.ChainId) _, secret, err := cmdUtils.CalculateSecret(account, epoch, keystorePath, core.ChainId) if err != nil { return err } + log.Debug("InitiateCommit: Secret: ", secret) + log.Debugf("Getting Salt for current epoch %d...", epoch) salt, err := cmdUtils.GetSalt(client, epoch) if err != nil { return err } + log.Debug("InitiateCommit: Salt: ", salt) seed := solsha3.SoliditySHA3([]string{"bytes32", "bytes32"}, []interface{}{"0x" + hex.EncodeToString(salt[:]), "0x" + hex.EncodeToString(secret)}) + log.Debugf("InitiateCommit: Calling HandleCommitState with arguments epoch = %d, seed = %v, rogueData = %+v", epoch, seed, rogueData) commitData, err := cmdUtils.HandleCommitState(client, epoch, seed, rogueData) if err != nil { return errors.New("Error in getting active assets: " + err.Error()) } + log.Debug("InitiateCommit: Commit Data: ", commitData) - _commitData = commitData - + log.Debug("InitiateCommit: Calling CreateMerkle() with argument Leaves = ", commitData.Leaves) merkleTree := utils.MerkleInterface.CreateMerkle(commitData.Leaves) + log.Debug("InitiateCommit: Merkle Tree: ", merkleTree) commitTxn, err := cmdUtils.Commit(client, config, account, epoch, seed, utils.MerkleInterface.GetMerkleRoot(merkleTree)) if err != nil { return errors.New("Error in committing data: " + err.Error()) } + log.Debug("InitiateCommit: Commit Transaction Hash: ", commitTxn) if commitTxn != core.NilHash { waitForBlockCompletionErr := razorUtils.WaitForBlockCompletion(client, commitTxn.String()) if waitForBlockCompletionErr != nil { log.Error("Error in WaitForBlockCompletion for commit: ", err) return errors.New("error in sending commit transaction") } + log.Debug("Updating GlobalCommitDataStruct with latest commitData and epoch...") + updateGlobalCommitDataStruct(commitData, epoch) + log.Debugf("InitiateCommit: Global commit data struct: %+v", globalCommitDataStruct) } - log.Debug("Saving committed data for recovery") + log.Debug("Saving committed data for recovery...") fileName, err := razorUtils.GetCommitDataFileName(account.Address) if err != nil { return errors.New("Error in getting file name to save committed data: " + err.Error()) } + log.Debug("InitiateCommit: Commit data file path: ", fileName) err = razorUtils.SaveDataToCommitJsonFile(fileName, epoch, commitData) if err != nil { @@ -358,11 +399,13 @@ func (*UtilsStruct) InitiateCommit(client *ethclient.Client, config types.Config //This function initiates the reveal func (*UtilsStruct) InitiateReveal(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, staker bindings.StructsStaker, rogueData types.Rogue) error { stakedAmount := staker.Stake + log.Debug("InitiateReveal: Staked Amount: ", stakedAmount) minStakeAmount, err := utils.UtilsInterface.GetMinStakeAmount(client) if err != nil { log.Error("Error in getting minimum stake amount: ", err) return err } + log.Debug("InitiateReveal: Minimum Stake Amount: ", minStakeAmount) if stakedAmount.Cmp(minStakeAmount) < 0 { log.Error("Stake is below minimum required. Kindly add stake to continue voting.") return nil @@ -371,64 +414,96 @@ func (*UtilsStruct) InitiateReveal(client *ethclient.Client, config types.Config if err != nil { return errors.New("Error in fetching last reveal: " + err.Error()) } + log.Debug("InitiateReveal: Last reveal was at epoch ", lastReveal) + if lastReveal >= epoch { log.Debugf("Since last reveal was at epoch: %d, won't reveal again in epoch: %d", lastReveal, epoch) return nil } + log.Debugf("InitiateReveal: Calling HandleRevealState with arguments staker = %+v, epoch = %d", staker, epoch) if err := cmdUtils.HandleRevealState(client, staker, epoch); err != nil { log.Error(err) return err } - log.Debug("Epoch last revealed: ", lastReveal) - if _commitData.AssignedCollections == nil && _commitData.SeqAllottedCollections == nil && _commitData.Leaves == nil { + nilCommitData := globalCommitDataStruct.AssignedCollections == nil && globalCommitDataStruct.SeqAllottedCollections == nil && globalCommitDataStruct.Leaves == nil + + if nilCommitData { + log.Debug("InitiateReveal: Global commit data is nil, getting the commit data from file...") fileName, err := razorUtils.GetCommitDataFileName(account.Address) if err != nil { log.Error("Error in getting file name to save committed data: ", err) return err } + log.Debug("InitiateReveal: Commit data file path: ", fileName) committedDataFromFile, err := razorUtils.ReadFromCommitJsonFile(fileName) if err != nil { - log.Errorf("Error in getting committed data from file %s: %t", fileName, err) + log.Errorf("Error in getting committed data from file %s: %v", fileName, err) return err } + log.Debug("InitiateReveal: Committed data from file: ", committedDataFromFile) if committedDataFromFile.Epoch != epoch { - log.Errorf("File %s doesn't contain latest committed data: %t", fileName, err) + log.Errorf("File %s doesn't contain latest committed data", fileName) return errors.New("commit data file doesn't contain latest committed data") } - _commitData.AssignedCollections = committedDataFromFile.AssignedCollections - _commitData.SeqAllottedCollections = committedDataFromFile.SeqAllottedCollections - _commitData.Leaves = committedDataFromFile.Leaves + log.Debug("Updating global commit data struct...") + updateGlobalCommitDataStruct(types.CommitData{ + Leaves: committedDataFromFile.Leaves, + SeqAllottedCollections: committedDataFromFile.SeqAllottedCollections, + AssignedCollections: committedDataFromFile.AssignedCollections, + }, epoch) + log.Debugf("InitiateReveal: Global Commit data struct: %+v", globalCommitDataStruct) } if rogueData.IsRogue && utils.Contains(rogueData.RogueMode, "reveal") { + log.Warn("YOU ARE REVEALING VALUES IN ROGUE MODE, THIS CAN INCUR PENALTIES!") var rogueCommittedData []*big.Int - for i := 0; i < len(_commitData.Leaves); i++ { + for i := 0; i < len(globalCommitDataStruct.Leaves); i++ { rogueCommittedData = append(rogueCommittedData, razorUtils.GetRogueRandomValue(10000000)) } - _commitData.Leaves = rogueCommittedData + globalCommitDataStruct.Leaves = rogueCommittedData + log.Debugf("InitiateReveal: Global Commit data struct in rogue mode: %+v", globalCommitDataStruct) } - razorPath, err := razorUtils.GetDefaultPath() - if err != nil { - return err - } - keystorePath := path.Join(razorPath, "keystore_files") + if globalCommitDataStruct.Epoch == epoch { + razorPath, err := razorUtils.GetDefaultPath() + if err != nil { + return err + } + log.Debug("InitiateReveal: .razor directory path: ", razorPath) + keystorePath := path.Join(razorPath, "keystore_files") + log.Debug("InitiateReveal: Keystore file path: ", keystorePath) - signature, _, err := cmdUtils.CalculateSecret(account, epoch, keystorePath, core.ChainId) - if err != nil { - return err - } - revealTxn, err := cmdUtils.Reveal(client, config, account, epoch, _commitData, signature) - if err != nil { - return errors.New("Reveal error: " + err.Error()) - } - if revealTxn != core.NilHash { - waitForBlockCompletionErr := razorUtils.WaitForBlockCompletion(client, revealTxn.String()) - if waitForBlockCompletionErr != nil { - log.Error("Error in WaitForBlockCompletionErr for reveal: ", err) + log.Debugf("InitiateReveal: Calling CalculateSecret() with argument epoch = %d, keystorePath = %s, chainId = %s", epoch, keystorePath, core.ChainId) + signature, _, err := cmdUtils.CalculateSecret(account, epoch, keystorePath, core.ChainId) + if err != nil { return err } + log.Debug("InitiateReveal: Signature: ", signature) + log.Debug("InitiateReveal: Assigned Collections: ", globalCommitDataStruct.AssignedCollections) + log.Debug("InitiateReveal: SeqAllottedCollections: ", globalCommitDataStruct.SeqAllottedCollections) + log.Debug("InitiateReveal: Leaves: ", globalCommitDataStruct.Leaves) + + commitDataToSend := types.CommitData{ + Leaves: globalCommitDataStruct.Leaves, + AssignedCollections: globalCommitDataStruct.AssignedCollections, + SeqAllottedCollections: globalCommitDataStruct.SeqAllottedCollections, + } + log.Debugf("InitiateReveal: Calling Reveal() with arguments epoch = %d, commitDataToSend = %+v, signature = %v", epoch, commitDataToSend, signature) + revealTxn, err := cmdUtils.Reveal(client, config, account, epoch, commitDataToSend, signature) + if err != nil { + return errors.New("Reveal error: " + err.Error()) + } + if revealTxn != core.NilHash { + waitForBlockCompletionErr := razorUtils.WaitForBlockCompletion(client, revealTxn.String()) + if waitForBlockCompletionErr != nil { + log.Error("Error in WaitForBlockCompletionErr for reveal: ", err) + return err + } + } + } else { + log.Error("The commit data is outdated, does not match with the latest epoch") + return errors.New("outdated commit data") } return nil } @@ -436,19 +511,22 @@ func (*UtilsStruct) InitiateReveal(client *ethclient.Client, config types.Config //This function initiates the propose func (*UtilsStruct) InitiatePropose(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, staker bindings.StructsStaker, blockNumber *big.Int, rogueData types.Rogue) error { stakedAmount := staker.Stake + log.Debug("InitiatePropose: Staked Amount: ", stakedAmount) minStakeAmount, err := utils.UtilsInterface.GetMinStakeAmount(client) if err != nil { log.Error("Error in getting minimum stake amount: ", err) return err } + log.Debug("InitiatePropose: Minimum Stake Amount: ", minStakeAmount) if stakedAmount.Cmp(minStakeAmount) < 0 { log.Error("Stake is below minimum required. Kindly add stake to continue voting.") return nil } - lastProposal, err := cmdUtils.GetLastProposedEpoch(client, blockNumber, staker.Id) + lastProposal, err := razorUtils.GetEpochLastProposed(client, staker.Id) if err != nil { return errors.New("Error in fetching last proposal: " + err.Error()) } + log.Debug("InitiatePropose: Last propose was in epoch ", lastProposal) if lastProposal >= epoch { log.Debugf("Since last propose was at epoch: %d, won't propose again in epoch: %d", epoch, lastProposal) return nil @@ -457,114 +535,62 @@ func (*UtilsStruct) InitiatePropose(client *ethclient.Client, config types.Confi if err != nil { return errors.New("Error in fetching last reveal: " + err.Error()) } + log.Debug("InitiatePropose: Last reveal was in epoch ", lastReveal) if lastReveal < epoch { log.Debugf("Cannot propose in epoch %d because last reveal was in epoch %d", epoch, lastReveal) return nil } - proposeTxn, err := cmdUtils.Propose(client, config, account, staker, epoch, blockNumber, rogueData) + log.Debugf("InitiatePropose: Calling Propose() with arguments staker = %+v, epoch = %d, blockNumber = %s, rogueData = %+v", staker, epoch, blockNumber, rogueData) + err = cmdUtils.Propose(client, config, account, staker, epoch, blockNumber, rogueData) if err != nil { return errors.New("Propose error: " + err.Error()) } - if proposeTxn != core.NilHash { - waitForBlockCompletionErr := razorUtils.WaitForBlockCompletion(client, proposeTxn.String()) - if waitForBlockCompletionErr != nil { - log.Error("Error in WaitForBlockCompletionErr for propose: ", err) - return err - } - } return nil } -//This function returns the last proposed epoch -func (*UtilsStruct) GetLastProposedEpoch(client *ethclient.Client, blockNumber *big.Int, stakerId uint32) (uint32, error) { - fromBlock, err := utils.UtilsInterface.CalculateBlockNumberAtEpochBeginning(client, core.EpochLength, blockNumber) - if err != nil { - return 0, errors.New("Not able to Fetch Block: " + err.Error()) - } - query := ethereum.FilterQuery{ - FromBlock: fromBlock, - ToBlock: blockNumber, - Addresses: []common.Address{ - common.HexToAddress(core.BlockManagerAddress), - }, - } - logs, err := utils.UtilsInterface.FilterLogsWithRetry(client, query) - if err != nil { - return 0, err - } - contractAbi, err := utils.ABIInterface.Parse(strings.NewReader(bindings.BlockManagerABI)) - if err != nil { - return 0, err - } - epochLastProposed := uint32(0) - - bufferPercent, err := cmdUtils.GetBufferPercent() - if err != nil { - return 0, err - } - - stateRemainingTime, err := utilsInterface.GetRemainingTimeOfCurrentState(client, bufferPercent) - if err != nil { - return 0, err - } - stateTimeout := time.NewTimer(time.Second * time.Duration(stateRemainingTime)) - -loop: - for _, vLog := range logs { - select { - case <-stateTimeout.C: - log.Error("State timeout!") - err = errors.New("propose state timeout") - break loop - default: - data, unpackErr := abiUtils.Unpack(contractAbi, "Proposed", vLog.Data) - if unpackErr != nil { - log.Error(unpackErr) - continue - } - topics := vLog.Topics - // topics[1] gives staker id in data type common.Hash - // Converting uint32 staker id to common.Hash to compare with staker id from topics - stakerIdInHash := common.BigToHash(big.NewInt(int64(stakerId))) - if stakerIdInHash == topics[1] && len(topics) > 1 { - epochLastProposed = data[0].(uint32) - } - } - } - if err != nil { - return 0, err - } - return epochLastProposed, nil -} - //This function calculates the secret func (*UtilsStruct) CalculateSecret(account types.Account, epoch uint32, keystorePath string, chainId *big.Int) ([]byte, []byte, error) { if chainId == nil { return nil, nil, errors.New("chainId is nil") } hash := solsha3.SoliditySHA3([]string{"address", "uint32", "uint256", "string"}, []interface{}{common.HexToAddress(account.Address), epoch, chainId, "razororacle"}) + log.Debug("CalculateSecret: Hash: ", hash) ethHash := utils.SignHash(hash) - + log.Debug("Hash generated for secret") + log.Debug("CalculateSecret: Ethereum signed hash: ", ethHash) signedData, err := accounts.AccountUtilsInterface.SignData(ethHash, account, keystorePath) if err != nil { return nil, nil, errors.New("Error in signing the data: " + err.Error()) } + log.Debug("CalculateSecret: SignedData: ", signedData) + log.Debugf("Checking whether recovered address from Hash: %v and Signed data: %v is same as given address...", hash, signedData) recoveredAddress, err := utils.EcRecover(hash, signedData) if err != nil { return nil, nil, errors.New("Error in verifying: " + err.Error()) } + log.Debug("CalculateSecret: Recovered Address: ", recoveredAddress) if recoveredAddress != common.HexToAddress(account.Address) { return nil, nil, errors.New("invalid verification") } + log.Debug("Address verified, generating secret....") if signedData[64] == 0 || signedData[64] == 1 { signedData[64] += 27 } secret := crypto.Keccak256(signedData) + log.Debug("Secret generated.") return signedData, secret, nil } +func updateGlobalCommitDataStruct(commitData types.CommitData, epoch uint32) types.CommitFileData { + globalCommitDataStruct.Leaves = commitData.Leaves + globalCommitDataStruct.AssignedCollections = commitData.AssignedCollections + globalCommitDataStruct.SeqAllottedCollections = commitData.SeqAllottedCollections + globalCommitDataStruct.Epoch = epoch + return globalCommitDataStruct +} + func init() { rootCmd.AddCommand(voteCmd) @@ -572,13 +598,17 @@ func init() { Address string Rogue bool RogueMode []string + Password string AutoClaimBounty bool + BackupNode []string ) voteCmd.Flags().StringVarP(&Address, "address", "a", "", "address of the staker") voteCmd.Flags().BoolVarP(&Rogue, "rogue", "r", false, "enable rogue mode to report wrong values") voteCmd.Flags().StringSliceVarP(&RogueMode, "rogueMode", "", []string{}, "type of rogue mode") + voteCmd.Flags().StringVarP(&Password, "password", "", "", "password path of the staker to protect the keystore") voteCmd.Flags().BoolVarP(&AutoClaimBounty, "autoClaimBounty", "", false, "auto claim bounty") + voteCmd.Flags().StringSliceVarP(&BackupNode, "backupNode", "", []string{}, "actions that backup node will ignore") addrErr := voteCmd.MarkFlagRequired("address") utils.CheckError("Address error: ", addrErr) diff --git a/cmd/vote_test.go b/cmd/vote_test.go index a0b837ee..ee8de3c5 100644 --- a/cmd/vote_test.go +++ b/cmd/vote_test.go @@ -3,9 +3,7 @@ package cmd import ( "encoding/hex" "errors" - "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" - Types "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/spf13/pflag" "github.com/stretchr/testify/mock" @@ -138,13 +136,14 @@ func TestExecuteVote(t *testing.T) { utilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet")) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) - utilsMock.On("AssignPassword").Return(tt.args.password) + utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) flagSetUtilsMock.On("GetStringAddress", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.address, tt.args.addressErr) + flagSetUtilsMock.On("GetStringSliceBackupNode", mock.Anything).Return([]string{}, nil) utilsMock.On("ConnectToClient", mock.AnythingOfType("string")).Return(client) flagSetUtilsMock.On("GetBoolRogue", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.rogueStatus, tt.args.rogueErr) flagSetUtilsMock.On("GetStringSliceRogueMode", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.rogueMode, tt.args.rogueModeErr) cmdUtilsMock.On("HandleExit").Return() - cmdUtilsMock.On("Vote", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.voteErr) + cmdUtilsMock.On("Vote", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.voteErr) osMock.On("Exit", mock.AnythingOfType("int")).Return() utils := &UtilsStruct{} @@ -158,172 +157,6 @@ func TestExecuteVote(t *testing.T) { } } -func TestGetLastProposedEpoch(t *testing.T) { - var client *ethclient.Client - blockNumber := big.NewInt(20) - - type args struct { - fromBlock *big.Int - fromBlockErr error - stakerId uint32 - logs []Types.Log - logsErr error - contractAbi abi.ABI - parseErr error - unpackedData []interface{} - unpackErr error - bufferPercent int32 - bufferPercentErr error - time int64 - timeErr error - } - tests := []struct { - name string - args args - want uint32 - wantErr error - }{ - { - name: "Test 1: When GetLastProposedBlock() executes successfully", - args: args{ - fromBlock: big.NewInt(0), - stakerId: 2, - logs: []Types.Log{ - { - Data: []byte{4, 2}, - Topics: []common.Hash{common.BigToHash(big.NewInt(1000)), common.BigToHash(big.NewInt(2))}, - }, - }, - contractAbi: abi.ABI{}, - unpackedData: convertToSliceOfInterface([]uint32{4, 2}), - bufferPercent: 1, - time: 0, - }, - want: 4, - wantErr: nil, - }, - { - name: "Test 2: When there is an error in getting logs", - args: args{ - logsErr: errors.New("logs error"), - }, - want: 0, - wantErr: errors.New("logs error"), - }, - { - name: "Test 3: When there is an error in getting contractAbi while parsing", - args: args{ - logs: []Types.Log{ - { - Data: []byte{4, 2}, - }, - }, - parseErr: errors.New("parse error"), - unpackedData: convertToSliceOfInterface([]uint32{4, 2}), - }, - want: 0, - wantErr: errors.New("parse error"), - }, - { - name: "Test 4: When there is an error in unpacking", - args: args{ - logs: []Types.Log{ - { - Data: []byte{4, 2}, - }, - }, - contractAbi: abi.ABI{}, - unpackErr: errors.New("unpack error"), - }, - want: 0, - wantErr: nil, - }, - { - name: "Test 5: When there is an error in fetching blocks", - args: args{ - fromBlockErr: errors.New("error in fetching blocks"), - }, - want: 0, - wantErr: errors.New("Not able to Fetch Block: error in fetching blocks"), - }, - { - name: "Test 6: When there is an error in getting bufferPercent", - args: args{ - fromBlock: big.NewInt(0), - stakerId: 2, - logs: []Types.Log{ - { - Data: []byte{4, 2}, - }, - }, - contractAbi: abi.ABI{}, - unpackedData: convertToSliceOfInterface([]uint32{4, 2}), - bufferPercentErr: errors.New("error in getting buffer percent"), - }, - want: 0, - wantErr: errors.New("error in getting buffer percent"), - }, - { - name: "Test 7: When there is an error in getting remaining time", - args: args{ - fromBlock: big.NewInt(0), - stakerId: 2, - logs: []Types.Log{ - { - Data: []byte{4, 2}, - }, - }, - contractAbi: abi.ABI{}, - unpackedData: convertToSliceOfInterface([]uint32{4, 2}), - bufferPercent: 1, - timeErr: errors.New("error in getting time"), - }, - want: 0, - wantErr: errors.New("error in getting time"), - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - - abiMock := new(mocks.AbiInterface) - utilsPkgMock := new(mocks2.Utils) - abiUtilsMock := new(mocks2.ABIUtils) - cmdUtilsMock := new(mocks.UtilsCmdInterface) - utilsMock := new(mocks.UtilsInterface) - utilsPkgMock2 := new(mocks2.Utils) - - utilsInterface = utilsPkgMock2 - razorUtils = utilsMock - abiUtils = abiMock - utils.UtilsInterface = utilsPkgMock - utils.ABIInterface = abiUtilsMock - cmdUtils = cmdUtilsMock - - utilsPkgMock.On("CalculateBlockNumberAtEpochBeginning", mock.AnythingOfType("*ethclient.Client"), mock.Anything, mock.Anything).Return(tt.args.fromBlock, tt.args.fromBlockErr) - abiUtilsMock.On("Parse", mock.Anything).Return(tt.args.contractAbi, tt.args.parseErr) - utilsPkgMock.On("FilterLogsWithRetry", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("ethereum.FilterQuery")).Return(tt.args.logs, tt.args.logsErr) - abiMock.On("Unpack", mock.Anything, mock.Anything, mock.Anything).Return(tt.args.unpackedData, tt.args.unpackErr) - cmdUtilsMock.On("GetBufferPercent").Return(tt.args.bufferPercent, tt.args.bufferPercentErr) - utilsPkgMock2.On("GetRemainingTimeOfCurrentState", mock.Anything, mock.Anything).Return(tt.args.time, tt.args.timeErr) - - utils := &UtilsStruct{} - got, err := utils.GetLastProposedEpoch(client, blockNumber, tt.args.stakerId) - if got != tt.want { - t.Errorf("GetLastProposedEpoch() got = %v, want %v", got, tt.want) - } - if err == nil || tt.wantErr == nil { - if err != tt.wantErr { - t.Errorf("Error for GetLastProposedEpoch(), got = %v, want = %v", err, tt.wantErr) - } - } else { - if err.Error() != tt.wantErr.Error() { - t.Errorf("Error for GetLastProposedEpoch(), got = %v, want = %v", err, tt.wantErr) - } - } - }) - } -} - func convertToSliceOfInterface(arr []uint32) []interface{} { s := make([]interface{}, len(arr)) for i, v := range arr { @@ -931,7 +764,6 @@ func TestInitiatePropose(t *testing.T) { lastProposalErr error lastReveal uint32 lastRevealErr error - proposeTxn common.Hash proposeTxnErr error } tests := []struct { @@ -947,7 +779,6 @@ func TestInitiatePropose(t *testing.T) { epoch: 5, lastProposal: 4, lastReveal: 6, - proposeTxn: common.BigToHash(big.NewInt(1)), }, wantErr: false, }, @@ -967,7 +798,6 @@ func TestInitiatePropose(t *testing.T) { epoch: 5, lastProposal: 4, lastReveal: 6, - proposeTxn: common.BigToHash(big.NewInt(1)), }, wantErr: false, }, @@ -1027,9 +857,9 @@ func TestInitiatePropose(t *testing.T) { utils.UtilsInterface = utilsPkgMock utilsPkgMock.On("GetMinStakeAmount", mock.AnythingOfType("*ethclient.Client")).Return(tt.args.minStakeAmount, tt.args.minStakeAmountErr) - cmdUtilsMock.On("GetLastProposedEpoch", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("*big.Int"), mock.AnythingOfType("uint32")).Return(tt.args.lastProposal, tt.args.lastProposalErr) + utilsMock.On("GetEpochLastProposed", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32")).Return(tt.args.lastProposal, tt.args.lastProposalErr) utilsMock.On("GetEpochLastRevealed", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32")).Return(tt.args.lastReveal, tt.args.lastRevealErr) - cmdUtilsMock.On("Propose", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.proposeTxn, tt.args.proposeTxnErr) + cmdUtilsMock.On("Propose", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.proposeTxnErr) utilsMock.On("WaitForBlockCompletion", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return(nil) ut := &UtilsStruct{} if err := ut.InitiatePropose(client, config, account, tt.args.epoch, tt.args.staker, blockNumber, rogueData); (err != nil) != tt.wantErr { @@ -1041,10 +871,11 @@ func TestInitiatePropose(t *testing.T) { func TestHandleBlock(t *testing.T) { var ( - client *ethclient.Client - account types.Account - blockNumber *big.Int - rogueData types.Rogue + client *ethclient.Client + account types.Account + blockNumber *big.Int + rogueData types.Rogue + backupNodeActionsToIgnore []string ) type args struct { @@ -1410,7 +1241,7 @@ func TestHandleBlock(t *testing.T) { cmdUtilsMock.On("InitiateCommit", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.initiateCommitErr) cmdUtilsMock.On("InitiateReveal", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.initiateRevealErr) cmdUtilsMock.On("InitiatePropose", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.initiateProposeErr) - cmdUtilsMock.On("HandleDispute", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.handleDisputeErr) + cmdUtilsMock.On("HandleDispute", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.handleDisputeErr) utilsPkgMock.On("IsFlagPassed", mock.AnythingOfType("string")).Return(tt.args.isFlagPassed) cmdUtilsMock.On("HandleClaimBounty", mock.Anything, mock.Anything, mock.Anything).Return(tt.args.handleClaimBountyErr) cmdUtilsMock.On("ClaimBlockReward", mock.Anything).Return(tt.args.claimBlockRewardTxn, tt.args.claimBlockRewardErr) @@ -1419,7 +1250,7 @@ func TestHandleBlock(t *testing.T) { utilsMock.On("WaitTillNextNSecs", mock.AnythingOfType("int32")).Return() lastVerification = tt.args.lastVerification ut := &UtilsStruct{} - ut.HandleBlock(client, account, blockNumber, tt.args.config, rogueData) + ut.HandleBlock(client, account, blockNumber, tt.args.config, rogueData, backupNodeActionsToIgnore) }) } } diff --git a/config.sh b/config.sh index 3f023062..10c150e4 100644 --- a/config.sh +++ b/config.sh @@ -37,4 +37,4 @@ read -rp "Gas Limit Increment : (2) " GAS_LIMIT if [ -z "$GAS_LIMIT" ]; then GAS_LIMIT=2 fi -$RAZOR setConfig -p $PROVIDER -b $BUFFER -g $GAS_MULTIPLIER -w $WAIT_TIME --gasprice $GAS_PRICE --gasLimit $GAS_LIMIT \ No newline at end of file +$RAZOR setConfig -p $PROVIDER -b $BUFFER -g $GAS_MULTIPLIER -w $WAIT_TIME --gasprice $GAS_PRICE --gasLimit $GAS_LIMIT --rpcTimeout 10 \ No newline at end of file diff --git a/core/constants.go b/core/constants.go index a81c150f..0bab7877 100644 --- a/core/constants.go +++ b/core/constants.go @@ -1,9 +1,8 @@ package core import ( - "math/big" - "github.com/ethereum/go-ethereum/common" + "math/big" ) var EpochLength int64 = 1200 @@ -13,3 +12,17 @@ var StateLength = uint64(EpochLength / NumberOfStates) var MaxRetries uint = 8 var NilHash = common.Hash{0x00} var BlockCompletionTimeout = 30 + +//Following are the default config values for all the config parameters + +var DefaultProvider = "http://127.0.0.1:8545" +var DefaultGasMultiplier = 1.0 +var DefaultBufferPercent = 20 +var DefaultGasPrice = 1 +var DefaultWaitTime = 1 +var DefaultGasLimit = 2 +var DefaultRPCTimeout = 10 +var DefaultLogLevel = "" + +//BlockNumberInterval is the interval in seconds after which blockNumber needs to be calculated again +var BlockNumberInterval = 5 diff --git a/core/types/block.go b/core/types/block.go index cc1d08d9..2fa61fd8 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -9,3 +9,10 @@ type Block struct { Block bindings.StructsBlock BlockMedians []*big.Int } + +type DisputesStruct struct { + LeafId uint16 + LastVisitedValue *big.Int + AccWeight *big.Int + Median *big.Int +} diff --git a/core/types/configurations.go b/core/types/configurations.go index 292129de..4a8a0b7c 100644 --- a/core/types/configurations.go +++ b/core/types/configurations.go @@ -8,4 +8,5 @@ type Configurations struct { GasPrice int32 LogLevel string GasLimitMultiplier float32 + RPCTimeout int64 } diff --git a/core/version.go b/core/version.go index 3b11d263..c4e88c5c 100644 --- a/core/version.go +++ b/core/version.go @@ -5,7 +5,7 @@ import "fmt" const ( VersionMajor = 1 // Major version component of the current release VersionMinor = 0 // Minor version component of the current release - VersionPatch = 4 // Patch version component of the current release + VersionPatch = 5 // Patch version component of the current release VersionMeta = "" // Version metadata to append to the version string ) diff --git a/logger/logger.go b/logger/logger.go index b3fbb8bd..fbef860e 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -1,20 +1,20 @@ package logger import ( - "context" "errors" "fmt" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/log" - "github.com/razor-network/goInfo" - "github.com/sirupsen/logrus" - "gopkg.in/natefinch/lumberjack.v2" "io" "math/big" "os" + "razor/block" "razor/core" "razor/path" "runtime" + + "github.com/ethereum/go-ethereum/ethclient" + "github.com/razor-network/goInfo" + "github.com/sirupsen/logrus" + "gopkg.in/natefinch/lumberjack.v2" ) type StandardLogger struct { @@ -55,9 +55,9 @@ func InitializeLogger(fileName string) { lumberJackLogger := &lumberjack.Logger{ Filename: logFilePath, - MaxSize: 5, - MaxBackups: 10, - MaxAge: 30, + MaxSize: 200, // Maximum Size of a log file + MaxBackups: 52, // Maximum number of log files + MaxAge: 365, // Maximum number of days to retain olf files } out := os.Stderr @@ -169,19 +169,17 @@ func (logger *StandardLogger) Fatalf(format string, args ...interface{}) { func SetEpochAndBlockNumber(client *ethclient.Client) { if client != nil { - latestHeader, err := client.HeaderByNumber(context.Background(), nil) - if err != nil { - log.Error("Error in fetching block: ", err) - return + latestBlock := block.GetLatestBlock() + if latestBlock != nil { + BlockNumber = latestBlock.Number + epoch := latestBlock.Time / uint64(core.EpochLength) + Epoch = uint32(epoch) } - BlockNumber = latestHeader.Number - - epoch := latestHeader.Time / uint64(core.EpochLength) - Epoch = uint32(epoch) } } func SetLoggerParameters(client *ethclient.Client, address string) { Address = address Client = client + go block.CalculateLatestBlock(client) } diff --git a/utils/asset.go b/utils/asset.go index cac6f597..41e3be35 100644 --- a/utils/asset.go +++ b/utils/asset.go @@ -162,6 +162,7 @@ func (*UtilsStruct) Aggregate(client *ethclient.Client, previousEpoch uint32, co return nil, err } if _, err := path.OSUtilsInterface.Stat(assetsFilePath); !errors.Is(err, os.ErrNotExist) { + log.Debug("Fetching the jobs from assets.json file...") jsonFile, err := path.OSUtilsInterface.Open(assetsFilePath) if err != nil { return nil, err @@ -195,7 +196,7 @@ func (*UtilsStruct) Aggregate(client *ethclient.Client, previousEpoch uint32, co if !Contains(overriddenJobIds, id) { job, err := UtilsInterface.GetActiveJob(client, id) if err != nil { - log.Errorf("Error in fetching job %d: %s", id, err) + log.Errorf("Error in fetching job %d: %v", id, err) continue } jobs = append(jobs, job) @@ -258,6 +259,7 @@ func (*UtilsStruct) GetDataToCommitFromJobs(jobs []bindings.StructsJob) ([]*big. if err != nil { continue } + log.Debugf("Job %s gives data %s", job.Url, dataToAppend) data = append(data, dataToAppend) weight = append(weight, job.Weight) } @@ -277,7 +279,7 @@ func (*UtilsStruct) GetDataToCommitFromJob(job bindings.StructsJob) (*big.Int, e start := time.Now() response, apiErr = UtilsInterface.GetDataFromAPI(job.Url) if apiErr != nil { - log.Error("Error in fetching data from API: ", apiErr) + log.Errorf("Error in fetching data from API %s: %v", job.Url, apiErr) return nil, apiErr } elapsed := time.Since(start).Seconds() diff --git a/utils/block.go b/utils/block.go index 7d2494d5..6c7b62d5 100644 --- a/utils/block.go +++ b/utils/block.go @@ -200,3 +200,23 @@ func (*UtilsStruct) GetBlockIndexToBeConfirmed(client *ethclient.Client) (int8, } return blockIndex, nil } + +func (*UtilsStruct) GetEpochLastProposed(client *ethclient.Client, stakerId uint32) (uint32, error) { + var ( + epochLastProposed uint32 + err error + ) + err = retry.Do( + func() error { + epochLastProposed, err = BlockManagerInterface.GetEpochLastProposed(client, stakerId) + if err != nil { + log.Error("Error in fetching epoch last proposed....Retrying") + return err + } + return nil + }, RetryInterface.RetryAttempts(core.MaxRetries)) + if err != nil { + return 0, err + } + return epochLastProposed, nil +} diff --git a/utils/block_test.go b/utils/block_test.go index 00bad127..54d8ec73 100644 --- a/utils/block_test.go +++ b/utils/block_test.go @@ -646,3 +646,64 @@ func TestGetStateBuffer(t *testing.T) { }) } } + +func TestGetEpochLastProposed(t *testing.T) { + var client *ethclient.Client + var callOpts bind.CallOpts + var stakerId uint32 + + type args struct { + epochLastProposed uint32 + epochLastProposedErr error + } + tests := []struct { + name string + args args + want uint32 + wantErr bool + }{ + { + name: "Test 1: When GetEpochLastProposed() executes successfully", + args: args{ + epochLastProposed: 100, + }, + want: 100, + wantErr: false, + }, + { + name: "Test 2: When there is an error in getting epochLastProposed", + args: args{ + epochLastProposedErr: errors.New("epochLastProposed error"), + }, + want: 0, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + retryMock := new(mocks.RetryUtils) + utilsMock := new(mocks.Utils) + blockManagerMock := new(mocks.BlockManagerUtils) + + optionsPackageStruct := OptionsPackageStruct{ + RetryInterface: retryMock, + UtilsInterface: utilsMock, + BlockManagerInterface: blockManagerMock, + } + utils := StartRazor(optionsPackageStruct) + + utilsMock.On("GetOptions").Return(callOpts) + blockManagerMock.On("GetEpochLastProposed", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32")).Return(tt.args.epochLastProposed, tt.args.epochLastProposedErr) + retryMock.On("RetryAttempts", mock.AnythingOfType("uint")).Return(retry.Attempts(1)) + + got, err := utils.GetEpochLastProposed(client, stakerId) + if (err != nil) != tt.wantErr { + t.Errorf("GetEpochLastProposed() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("GetEpochLastProposed() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/utils/client_methods.go b/utils/client_methods.go index ef11c480..731ba786 100644 --- a/utils/client_methods.go +++ b/utils/client_methods.go @@ -11,14 +11,14 @@ import ( "razor/core" ) -func (*UtilsStruct) GetPendingNonceAtWithRetry(client *ethclient.Client, accountAddress common.Address) (uint64, error) { +func (*UtilsStruct) GetNonceAtWithRetry(client *ethclient.Client, accountAddress common.Address) (uint64, error) { var ( nonce uint64 err error ) err = retry.Do( func() error { - nonce, err = ClientInterface.PendingNonceAt(client, context.Background(), accountAddress) + nonce, err = ClientInterface.NonceAt(client, context.Background(), accountAddress) if err != nil { log.Error("Error in fetching nonce.... Retrying") return err diff --git a/utils/client_methods_test.go b/utils/client_methods_test.go index b9f77cd8..120a5629 100644 --- a/utils/client_methods_test.go +++ b/utils/client_methods_test.go @@ -297,7 +297,7 @@ func TestUtilsStruct_GetLatestBlockWithRetry(t *testing.T) { } } -func TestUtilsStruct_GetPendingNonceAtWithRetry(t *testing.T) { +func TestUtilsStruct_GetNonceAtWithRetry(t *testing.T) { var client *ethclient.Client var accountAddress common.Address @@ -338,16 +338,16 @@ func TestUtilsStruct_GetPendingNonceAtWithRetry(t *testing.T) { } utils := StartRazor(optionsPackageStruct) - clientMock.On("PendingNonceAt", mock.AnythingOfType("*ethclient.Client"), context.Background(), mock.AnythingOfType("common.Address")).Return(tt.args.nonce, tt.args.nonceErr) + clientMock.On("NonceAt", mock.AnythingOfType("*ethclient.Client"), context.Background(), mock.AnythingOfType("common.Address")).Return(tt.args.nonce, tt.args.nonceErr) retryMock.On("RetryAttempts", mock.AnythingOfType("uint")).Return(retry.Attempts(1)) - got, err := utils.GetPendingNonceAtWithRetry(client, accountAddress) + got, err := utils.GetNonceAtWithRetry(client, accountAddress) if (err != nil) != tt.wantErr { - t.Errorf("GetPendingNonceAtWithRetry() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetNonceAtWithRetry() error = %v, wantErr %v", err, tt.wantErr) return } if got != tt.want { - t.Errorf("GetPendingNonceAtWithRetry() got = %v, want %v", got, tt.want) + t.Errorf("GetNonceAtWithRetry() got = %v, want %v", got, tt.want) } }) } diff --git a/utils/common.go b/utils/common.go index 49d231c3..c326d3b4 100644 --- a/utils/common.go +++ b/utils/common.go @@ -192,7 +192,7 @@ func (*UtilsStruct) Prng(max uint32, prngHashes []byte) *big.Int { func (*UtilsStruct) CalculateBlockNumberAtEpochBeginning(client *ethclient.Client, epochLength int64, currentBlockNumber *big.Int) (*big.Int, error) { block, err := ClientInterface.HeaderByNumber(client, context.Background(), currentBlockNumber) if err != nil { - log.Errorf("Error in fetching block : %s", err) + log.Error("Error in fetching block: ", err) return nil, err } current_epoch := block.Time / uint64(core.EpochLength) @@ -200,7 +200,7 @@ func (*UtilsStruct) CalculateBlockNumberAtEpochBeginning(client *ethclient.Clien previousBlock, err := ClientInterface.HeaderByNumber(client, context.Background(), big.NewInt(int64(previousBlockNumber))) if err != nil { - log.Errorf("Err in fetching Previous block : %s", err) + log.Error("Err in fetching Previous block: ", err) return nil, err } previousBlockActualTimestamp := previousBlock.Time @@ -259,16 +259,19 @@ func (*UtilsStruct) AssignLogFile(flagSet *pflag.FlagSet) { if UtilsInterface.IsFlagPassed("logFile") { fileName, err := FlagSetInterface.GetLogFileName(flagSet) if err != nil { - log.Fatalf("Error in getting file name : ", err) + log.Fatal("Error in getting file name: ", err) } + log.Debug("Log file name: ", fileName) logger.InitializeLogger(fileName) + } else { + log.Debug("No `logFile` flag passed, not storing logs in any file") } } -func (*UtilsStruct) SaveDataToProposeJsonFile(filePath string, epoch uint32, proposeData types.ProposeData) error { +func (*UtilsStruct) SaveDataToProposeJsonFile(filePath string, proposeData types.ProposeFileData) error { var data types.ProposeFileData - data.Epoch = epoch + data.Epoch = proposeData.Epoch data.MediansData = proposeData.MediansData data.RevealedCollectionIds = proposeData.RevealedCollectionIds data.RevealedDataMaps = proposeData.RevealedDataMaps diff --git a/utils/common_test.go b/utils/common_test.go index 1889baa1..0ffff85b 100644 --- a/utils/common_test.go +++ b/utils/common_test.go @@ -1107,8 +1107,7 @@ func TestSaveDataToCommitJsonFile(t *testing.T) { func TestSaveDataToProposeJsonFile(t *testing.T) { var ( filePath string - epoch uint32 - proposeData Types.ProposeData + proposeData Types.ProposeFileData ) type args struct { @@ -1157,7 +1156,7 @@ func TestSaveDataToProposeJsonFile(t *testing.T) { jsonMock.On("Marshal", mock.Anything).Return(tt.args.jsonData, tt.args.jsonDataErr) osMock.On("WriteFile", mock.Anything, mock.Anything, mock.Anything).Return(tt.args.writeFileErr) - if err := utils.SaveDataToProposeJsonFile(filePath, epoch, proposeData); (err != nil) != tt.wantErr { + if err := utils.SaveDataToProposeJsonFile(filePath, proposeData); (err != nil) != tt.wantErr { t.Errorf("SaveDataToProposeJsonFile() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/utils/interface.go b/utils/interface.go index 5e1f6a99..541f7f7f 100644 --- a/utils/interface.go +++ b/utils/interface.go @@ -71,7 +71,7 @@ var FlagSetInterface FlagSetUtils type Utils interface { SuggestGasPriceWithRetry(client *ethclient.Client) (*big.Int, error) MultiplyFloatAndBigInt(bigIntVal *big.Int, floatingVal float64) *big.Int - GetPendingNonceAtWithRetry(client *ethclient.Client, accountAddress common.Address) (uint64, error) + GetNonceAtWithRetry(client *ethclient.Client, accountAddress common.Address) (uint64, error) GetGasPrice(client *ethclient.Client, config types.Configurations) *big.Int GetTxnOpts(transactionData types.TransactionOptions) *bind.TransactOpts GetGasLimit(transactionData types.TransactionOptions, txnOpts *bind.TransactOpts) (uint64, error) @@ -144,7 +144,7 @@ type Utils interface { GetEpoch(client *ethclient.Client) (uint32, error) SaveDataToCommitJsonFile(filePath string, epoch uint32, commitData types.CommitData) error ReadFromCommitJsonFile(filePath string) (types.CommitFileData, error) - SaveDataToProposeJsonFile(filePath string, epoch uint32, proposeData types.ProposeData) error + SaveDataToProposeJsonFile(filePath string, proposeData types.ProposeFileData) error ReadFromProposeJsonFile(filePath string) (types.ProposeFileData, error) SaveDataToDisputeJsonFile(filePath string, bountyIdQueue []uint32) error ReadFromDisputeJsonFile(filePath string) (types.DisputeFileData, error) @@ -170,7 +170,7 @@ type Utils interface { AssignLogFile(flagSet *pflag.FlagSet) CalculateBlockNumberAtEpochBeginning(client *ethclient.Client, epochLength int64, currentBlockNumber *big.Int) (*big.Int, error) GetStateName(stateNumber int64) string - Shuffle(slice []uint32) []uint32 + GetEpochLastProposed(client *ethclient.Client, stakerId uint32) (uint32, error) } type EthClientUtils interface { @@ -181,7 +181,7 @@ type ClientUtils interface { TransactionReceipt(client *ethclient.Client, ctx context.Context, txHash common.Hash) (*Types.Receipt, error) BalanceAt(client *ethclient.Client, ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error) HeaderByNumber(client *ethclient.Client, ctx context.Context, number *big.Int) (*Types.Header, error) - PendingNonceAt(client *ethclient.Client, ctx context.Context, account common.Address) (uint64, error) + NonceAt(client *ethclient.Client, ctx context.Context, account common.Address) (uint64, error) SuggestGasPrice(client *ethclient.Client, ctx context.Context) (*big.Int, error) EstimateGas(client *ethclient.Client, ctx context.Context, msg ethereum.CallMsg) (uint64, error) FilterLogs(client *ethclient.Client, ctx context.Context, q ethereum.FilterQuery) ([]Types.Log, error) @@ -242,6 +242,7 @@ type BlockManagerUtils interface { MaxAltBlocks(client *ethclient.Client) (uint8, error) SortedProposedBlockIds(client *ethclient.Client, arg0 uint32, arg1 *big.Int) (uint32, error) GetBlockIndexToBeConfirmed(client *ethclient.Client) (int8, error) + GetEpochLastProposed(client *ethclient.Client, stakerId uint32) (uint32, error) } type StakeManagerUtils interface { diff --git a/utils/math.go b/utils/math.go index c0bb79a7..c908806d 100644 --- a/utils/math.go +++ b/utils/math.go @@ -167,11 +167,13 @@ func GetRogueRandomMedianValue() uint32 { return uint32(rogueRandomMedianValue.Int64()) } -func (*UtilsStruct) Shuffle(slice []uint32) []uint32 { +func Shuffle(slice []uint32) []uint32 { + copiedSlice := make([]uint32, len(slice)) + copy(copiedSlice, slice) r := mathRand.New(mathRand.NewSource(time.Now().Unix())) - for n := len(slice); n > 0; n-- { + for n := len(copiedSlice); n > 0; n-- { randIndex := r.Intn(n) - slice[n-1], slice[randIndex] = slice[randIndex], slice[n-1] + copiedSlice[n-1], copiedSlice[randIndex] = copiedSlice[randIndex], copiedSlice[n-1] } - return slice + return copiedSlice } diff --git a/utils/math_test.go b/utils/math_test.go index c96e7ecb..da98982e 100644 --- a/utils/math_test.go +++ b/utils/math_test.go @@ -905,7 +905,7 @@ func TestShuffle(t *testing.T) { args: args{ slice: []uint32{12, 20, 6, 45, 32}, }, - want: true, + want: false, }, { name: "Test 2: When array is nil", @@ -919,16 +919,19 @@ func TestShuffle(t *testing.T) { args: args{ slice: []uint32{12}, }, - want: false, + want: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - ut := &UtilsStruct{} - got := ut.Shuffle(tt.args.slice) - if !UintArrayEquals(got, tt.args.slice) && !IndexNotEqual(got, tt.args.slice) { - t.Errorf("TestShuffle() = %v, want %v", got, tt.want) + log.Info("OriginalSlice: ", tt.args.slice) + got := Shuffle(tt.args.slice) + log.Info("ShuffledSlice: ", got) + log.Info("OriginalSlice after shuffling: ", tt.args.slice) + equalStatus := UintArrayEquals(got, tt.args.slice) + if equalStatus != tt.want { + t.Errorf("TestShuffle() = %v, want = %v", equalStatus, tt.want) } }) } diff --git a/utils/mocks/block_manager_utils.go b/utils/mocks/block_manager_utils.go index 25c134cf..072fb543 100644 --- a/utils/mocks/block_manager_utils.go +++ b/utils/mocks/block_manager_utils.go @@ -58,6 +58,27 @@ func (_m *BlockManagerUtils) GetBlockIndexToBeConfirmed(client *ethclient.Client return r0, r1 } +// GetEpochLastProposed provides a mock function with given fields: client, stakerId +func (_m *BlockManagerUtils) GetEpochLastProposed(client *ethclient.Client, stakerId uint32) (uint32, error) { + ret := _m.Called(client, stakerId) + + var r0 uint32 + if rf, ok := ret.Get(0).(func(*ethclient.Client, uint32) uint32); ok { + r0 = rf(client, stakerId) + } else { + r0 = ret.Get(0).(uint32) + } + + var r1 error + if rf, ok := ret.Get(1).(func(*ethclient.Client, uint32) error); ok { + r1 = rf(client, stakerId) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetNumProposedBlocks provides a mock function with given fields: client, epoch func (_m *BlockManagerUtils) GetNumProposedBlocks(client *ethclient.Client, epoch uint32) (uint8, error) { ret := _m.Called(client, epoch) diff --git a/utils/mocks/client_utils.go b/utils/mocks/client_utils.go index f551f3a6..8c8eda1d 100644 --- a/utils/mocks/client_utils.go +++ b/utils/mocks/client_utils.go @@ -112,8 +112,8 @@ func (_m *ClientUtils) HeaderByNumber(client *ethclient.Client, ctx context.Cont return r0, r1 } -// PendingNonceAt provides a mock function with given fields: client, ctx, account -func (_m *ClientUtils) PendingNonceAt(client *ethclient.Client, ctx context.Context, account common.Address) (uint64, error) { +// NonceAt provides a mock function with given fields: client, ctx, account +func (_m *ClientUtils) NonceAt(client *ethclient.Client, ctx context.Context, account common.Address) (uint64, error) { ret := _m.Called(client, ctx, account) var r0 uint64 diff --git a/utils/mocks/utils.go b/utils/mocks/utils.go index 86f46c62..cf68ec9f 100644 --- a/utils/mocks/utils.go +++ b/utils/mocks/utils.go @@ -863,6 +863,27 @@ func (_m *Utils) GetEpochLastCommitted(client *ethclient.Client, stakerId uint32 return r0, r1 } +// GetEpochLastProposed provides a mock function with given fields: client, stakerId +func (_m *Utils) GetEpochLastProposed(client *ethclient.Client, stakerId uint32) (uint32, error) { + ret := _m.Called(client, stakerId) + + var r0 uint32 + if rf, ok := ret.Get(0).(func(*ethclient.Client, uint32) uint32); ok { + r0 = rf(client, stakerId) + } else { + r0 = ret.Get(0).(uint32) + } + + var r1 error + if rf, ok := ret.Get(1).(func(*ethclient.Client, uint32) error); ok { + r1 = rf(client, stakerId) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetEpochLastRevealed provides a mock function with given fields: client, stakerId func (_m *Utils) GetEpochLastRevealed(client *ethclient.Client, stakerId uint32) (uint32, error) { ret := _m.Called(client, stakerId) @@ -1141,6 +1162,27 @@ func (_m *Utils) GetMinStakeAmount(client *ethclient.Client) (*big.Int, error) { return r0, r1 } +// GetNonceAtWithRetry provides a mock function with given fields: client, accountAddress +func (_m *Utils) GetNonceAtWithRetry(client *ethclient.Client, accountAddress common.Address) (uint64, error) { + ret := _m.Called(client, accountAddress) + + var r0 uint64 + if rf, ok := ret.Get(0).(func(*ethclient.Client, common.Address) uint64); ok { + r0 = rf(client, accountAddress) + } else { + r0 = ret.Get(0).(uint64) + } + + var r1 error + if rf, ok := ret.Get(1).(func(*ethclient.Client, common.Address) error); ok { + r1 = rf(client, accountAddress) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetNumActiveCollections provides a mock function with given fields: client func (_m *Utils) GetNumActiveCollections(client *ethclient.Client) (uint16, error) { ret := _m.Called(client) @@ -1239,27 +1281,6 @@ func (_m *Utils) GetOptions() bind.CallOpts { return r0 } -// GetPendingNonceAtWithRetry provides a mock function with given fields: client, accountAddress -func (_m *Utils) GetPendingNonceAtWithRetry(client *ethclient.Client, accountAddress common.Address) (uint64, error) { - ret := _m.Called(client, accountAddress) - - var r0 uint64 - if rf, ok := ret.Get(0).(func(*ethclient.Client, common.Address) uint64); ok { - r0 = rf(client, accountAddress) - } else { - r0 = ret.Get(0).(uint64) - } - - var r1 error - if rf, ok := ret.Get(1).(func(*ethclient.Client, common.Address) error); ok { - r1 = rf(client, accountAddress) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // GetProposedBlock provides a mock function with given fields: client, epoch, proposedBlockId func (_m *Utils) GetProposedBlock(client *ethclient.Client, epoch uint32, proposedBlockId uint32) (bindings.StructsBlock, error) { ret := _m.Called(client, epoch, proposedBlockId) @@ -1935,13 +1956,13 @@ func (_m *Utils) SaveDataToDisputeJsonFile(filePath string, bountyIdQueue []uint return r0 } -// SaveDataToProposeJsonFile provides a mock function with given fields: filePath, epoch, proposeData -func (_m *Utils) SaveDataToProposeJsonFile(filePath string, epoch uint32, proposeData types.ProposeData) error { - ret := _m.Called(filePath, epoch, proposeData) +// SaveDataToProposeJsonFile provides a mock function with given fields: filePath, proposeData +func (_m *Utils) SaveDataToProposeJsonFile(filePath string, proposeData types.ProposeFileData) error { + ret := _m.Called(filePath, proposeData) var r0 error - if rf, ok := ret.Get(0).(func(string, uint32, types.ProposeData) error); ok { - r0 = rf(filePath, epoch, proposeData) + if rf, ok := ret.Get(0).(func(string, types.ProposeFileData) error); ok { + r0 = rf(filePath, proposeData) } else { r0 = ret.Error(0) } diff --git a/utils/options.go b/utils/options.go index 689911b4..d3e18cb3 100644 --- a/utils/options.go +++ b/utils/options.go @@ -27,6 +27,7 @@ func (*UtilsStruct) GetOptions() bind.CallOpts { } func (*UtilsStruct) GetTxnOpts(transactionData types.TransactionOptions) *bind.TransactOpts { + log.Debug("Getting transaction options...") defaultPath, err := PathInterface.GetDefaultPath() CheckError("Error in fetching default path: ", err) keystorePath := path.Join(defaultPath, "keystore_files") @@ -34,8 +35,8 @@ func (*UtilsStruct) GetTxnOpts(transactionData types.TransactionOptions) *bind.T if privateKey == nil || err != nil { CheckError("Error in fetching private key: ", errors.New(transactionData.AccountAddress+" not present in razor-go")) } - nonce, err := UtilsInterface.GetPendingNonceAtWithRetry(transactionData.Client, common.HexToAddress(transactionData.AccountAddress)) - CheckError("Error in fetching pending nonce: ", err) + nonce, err := UtilsInterface.GetNonceAtWithRetry(transactionData.Client, common.HexToAddress(transactionData.AccountAddress)) + CheckError("Error in fetching nonce: ", err) gasPrice := UtilsInterface.GetGasPrice(transactionData.Client, transactionData.Config) txnOpts, err := BindInterface.NewKeyedTransactorWithChainID(privateKey, transactionData.ChainId) diff --git a/utils/options_test.go b/utils/options_test.go index 7fdb910a..b48bf082 100644 --- a/utils/options_test.go +++ b/utils/options_test.go @@ -286,7 +286,7 @@ func Test_utils_GetTxnOpts(t *testing.T) { pathMock.On("GetDefaultPath").Return(tt.args.path, tt.args.pathErr) accountsMock.On("GetPrivateKey", mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(tt.args.privateKey, nil) - utilsMock.On("GetPendingNonceAtWithRetry", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("common.Address")).Return(tt.args.nonce, tt.args.nonceErr) + utilsMock.On("GetNonceAtWithRetry", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("common.Address")).Return(tt.args.nonce, tt.args.nonceErr) utilsMock.On("GetGasPrice", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("types.Configurations")).Return(gasPrice) bindMock.On("NewKeyedTransactorWithChainID", mock.AnythingOfType("*ecdsa.PrivateKey"), mock.AnythingOfType("*big.Int")).Return(tt.args.txnOpts, tt.args.txnOptsErr) utilsMock.On("GetGasLimit", transactionData, txnOpts).Return(tt.args.gasLimit, tt.args.gasLimitErr) diff --git a/utils/password.go b/utils/password.go index 5d1979a8..cade81b7 100644 --- a/utils/password.go +++ b/utils/password.go @@ -1,8 +1,11 @@ package utils import ( + "bufio" "errors" "github.com/manifoldco/promptui" + "github.com/spf13/pflag" + "os" "unicode" ) @@ -46,7 +49,31 @@ func validatePrivateKey(input string) error { return nil } -func AssignPassword() string { +func GetPasswordFromFile(path string) string { + file, err := os.Open(path) + if err != nil { + log.Fatal(err) + } + log.Info("Getting password from the first line of file at described location") + defer file.Close() + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + return scanner.Text() + } + if err := scanner.Err(); err != nil { + log.Fatal(err) + } + return "" +} + +func AssignPassword(flagSet *pflag.FlagSet) string { + if UtilsInterface.IsFlagPassed("password") { + log.Warn("Password flag is passed") + log.Warn("This is a unsecure way to use razor-go") + passwordPath, _ := flagSet.GetString("password") + return GetPasswordFromFile(passwordPath) + } return PasswordPrompt() } diff --git a/utils/struct-utils.go b/utils/struct-utils.go index 7990b6ab..154bd5ed 100644 --- a/utils/struct-utils.go +++ b/utils/struct-utils.go @@ -5,6 +5,7 @@ import ( "context" "crypto/ecdsa" "encoding/json" + "errors" "io" "io/fs" "math/big" @@ -13,6 +14,7 @@ import ( coretypes "razor/core/types" "razor/path" "razor/pkg/bindings" + "reflect" "time" "github.com/avast/retry-go" @@ -25,6 +27,8 @@ import ( "github.com/spf13/pflag" ) +var RPCTimeout int64 + func StartRazor(optionsPackageStruct OptionsPackageStruct) Utils { UtilsInterface = optionsPackageStruct.UtilsInterface EthClient = optionsPackageStruct.EthClient @@ -51,54 +55,159 @@ func StartRazor(optionsPackageStruct OptionsPackageStruct) Utils { return &UtilsStruct{} } +func InvokeFunctionWithTimeout(interfaceName interface{}, methodName string, args ...interface{}) []reflect.Value { + var functionCall []reflect.Value + var gotFunction = make(chan bool) + ctx, cancel := context.WithTimeout(context.Background(), time.Duration(RPCTimeout)*time.Second) + defer cancel() + + go func() { + inputs := make([]reflect.Value, len(args)) + for i := range args { + inputs[i] = reflect.ValueOf(args[i]) + } + log.Debug("Blockchain function: ", methodName) + functionCall = reflect.ValueOf(interfaceName).MethodByName(methodName).Call(inputs) + gotFunction <- true + }() + for { + select { + case <-ctx.Done(): + log.Errorf("%s function timeout!", methodName) + log.Debug("Kindly check your connection") + return nil + + case <-gotFunction: + return functionCall + } + } +} + +func CheckIfAnyError(result []reflect.Value) error { + if result == nil { + return errors.New("RPC timeout error") + } + + errorDataType := reflect.TypeOf((*error)(nil)).Elem() + errorIndexInReturnedValues := -1 + + for i := range result { + returnedValue := result[i] + returnedValueDataType := reflect.TypeOf(returnedValue.Interface()) + if returnedValueDataType != nil { + if returnedValueDataType.Implements(errorDataType) { + errorIndexInReturnedValues = i + } + } + } + if errorIndexInReturnedValues == -1 { + return nil + } + returnedError := result[errorIndexInReturnedValues].Interface() + if returnedError != nil { + return returnedError.(error) + } + return nil +} + func (b BlockManagerStruct) GetBlockIndexToBeConfirmed(client *ethclient.Client) (int8, error) { blockManager, opts := UtilsInterface.GetBlockManagerWithOpts(client) - return blockManager.BlockIndexToBeConfirmed(&opts) + returnedValues := InvokeFunctionWithTimeout(blockManager, "BlockIndexToBeConfirmed", &opts) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return -1, returnedError + } + return returnedValues[0].Interface().(int8), nil } func (s StakeManagerStruct) WithdrawInitiationPeriod(client *ethclient.Client) (uint16, error) { stakeManager, opts := UtilsInterface.GetStakeManagerWithOpts(client) - return stakeManager.WithdrawInitiationPeriod(&opts) + returnedValues := InvokeFunctionWithTimeout(stakeManager, "WithdrawInitiationPeriod", &opts) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return 0, returnedError + } + return returnedValues[0].Interface().(uint16), nil } func (a AssetManagerStruct) GetNumJobs(client *ethclient.Client) (uint16, error) { collectionManager, opts := UtilsInterface.GetCollectionManagerWithOpts(client) - return collectionManager.GetNumJobs(&opts) + returnedValues := InvokeFunctionWithTimeout(collectionManager, "GetNumJobs", &opts) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return 0, returnedError + } + return returnedValues[0].Interface().(uint16), nil } func (a AssetManagerStruct) GetCollection(client *ethclient.Client, id uint16) (bindings.StructsCollection, error) { collectionManager, opts := UtilsInterface.GetCollectionManagerWithOpts(client) - return collectionManager.GetCollection(&opts, id) + returnedValues := InvokeFunctionWithTimeout(collectionManager, "GetCollection", &opts, id) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return bindings.StructsCollection{}, returnedError + } + return returnedValues[0].Interface().(bindings.StructsCollection), nil } func (a AssetManagerStruct) GetJob(client *ethclient.Client, id uint16) (bindings.StructsJob, error) { collectionManager, opts := UtilsInterface.GetCollectionManagerWithOpts(client) - return collectionManager.GetJob(&opts, id) + returnedValues := InvokeFunctionWithTimeout(collectionManager, "GetJob", &opts, id) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return bindings.StructsJob{}, returnedError + } + return returnedValues[0].Interface().(bindings.StructsJob), nil } func (a AssetManagerStruct) GetCollectionIdFromIndex(client *ethclient.Client, index uint16) (uint16, error) { collectionManager, opts := UtilsInterface.GetCollectionManagerWithOpts(client) - return collectionManager.LeafIdToCollectionIdRegistry(&opts, index) + returnedValues := InvokeFunctionWithTimeout(collectionManager, "LeafIdToCollectionIdRegistry", &opts, index) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return 0, returnedError + } + return returnedValues[0].Interface().(uint16), nil } func (a AssetManagerStruct) GetCollectionIdFromLeafId(client *ethclient.Client, leafId uint16) (uint16, error) { collectionManager, opts := UtilsInterface.GetCollectionManagerWithOpts(client) - return collectionManager.GetCollectionIdFromLeafId(&opts, leafId) + returnedValues := InvokeFunctionWithTimeout(collectionManager, "GetCollectionIdFromLeafId", &opts, leafId) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return 0, returnedError + } + return returnedValues[0].Interface().(uint16), nil } func (a AssetManagerStruct) GetLeafIdOfACollection(client *ethclient.Client, collectionId uint16) (uint16, error) { collectionManager, opts := UtilsInterface.GetCollectionManagerWithOpts(client) - return collectionManager.GetLeafIdOfCollection(&opts, collectionId) + returnedValues := InvokeFunctionWithTimeout(collectionManager, "GetLeafIdOfCollection", &opts, collectionId) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return 0, returnedError + } + return returnedValues[0].Interface().(uint16), nil } func (v VoteManagerStruct) ToAssign(client *ethclient.Client) (uint16, error) { voteManager, opts := UtilsInterface.GetVoteManagerWithOpts(client) - return voteManager.ToAssign(&opts) + returnedValues := InvokeFunctionWithTimeout(voteManager, "ToAssign", &opts) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return 0, returnedError + } + return returnedValues[0].Interface().(uint16), nil } func (v VoteManagerStruct) GetSaltFromBlockchain(client *ethclient.Client) ([32]byte, error) { voteManager, opts := UtilsInterface.GetVoteManagerWithOpts(client) - return voteManager.GetSalt(&opts) + returnedValues := InvokeFunctionWithTimeout(voteManager, "GetSalt", &opts) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return [32]byte{}, returnedError + } + return returnedValues[0].Interface().([32]byte), nil } func (a AccountsStruct) GetPrivateKey(address string, password string, keystorePath string) (*ecdsa.PrivateKey, error) { @@ -107,127 +216,279 @@ func (a AccountsStruct) GetPrivateKey(address string, password string, keystoreP func (b BlockManagerStruct) GetNumProposedBlocks(client *ethclient.Client, epoch uint32) (uint8, error) { blockManager, opts := UtilsInterface.GetBlockManagerWithOpts(client) - return blockManager.GetNumProposedBlocks(&opts, epoch) + returnedValues := InvokeFunctionWithTimeout(blockManager, "GetNumProposedBlocks", &opts, epoch) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return 0, returnedError + } + return returnedValues[0].Interface().(uint8), nil } func (b BlockManagerStruct) GetProposedBlock(client *ethclient.Client, epoch uint32, proposedBlock uint32) (bindings.StructsBlock, error) { blockManager, opts := UtilsInterface.GetBlockManagerWithOpts(client) - return blockManager.GetProposedBlock(&opts, epoch, proposedBlock) + returnedValues := InvokeFunctionWithTimeout(blockManager, "GetProposedBlock", &opts, epoch, proposedBlock) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return bindings.StructsBlock{}, returnedError + } + return returnedValues[0].Interface().(bindings.StructsBlock), nil } func (b BlockManagerStruct) GetBlock(client *ethclient.Client, epoch uint32) (bindings.StructsBlock, error) { blockManager, opts := UtilsInterface.GetBlockManagerWithOpts(client) - return blockManager.GetBlock(&opts, epoch) + returnedValues := InvokeFunctionWithTimeout(blockManager, "GetBlock", &opts, epoch) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return bindings.StructsBlock{}, returnedError + } + return returnedValues[0].Interface().(bindings.StructsBlock), nil } func (b BlockManagerStruct) MinStake(client *ethclient.Client) (*big.Int, error) { blockManager, opts := UtilsInterface.GetBlockManagerWithOpts(client) - return blockManager.MinStake(&opts) + returnedValues := InvokeFunctionWithTimeout(blockManager, "MinStake", &opts) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return nil, returnedError + } + return returnedValues[0].Interface().(*big.Int), nil } func (b BlockManagerStruct) StateBuffer(client *ethclient.Client) (uint8, error) { blockManager, opts := UtilsInterface.GetBlockManagerWithOpts(client) - return blockManager.Buffer(&opts) + returnedValues := InvokeFunctionWithTimeout(blockManager, "Buffer", &opts) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return 0, returnedError + } + return returnedValues[0].Interface().(uint8), nil } func (b BlockManagerStruct) MaxAltBlocks(client *ethclient.Client) (uint8, error) { blockManager, opts := UtilsInterface.GetBlockManagerWithOpts(client) - return blockManager.MaxAltBlocks(&opts) + returnedValues := InvokeFunctionWithTimeout(blockManager, "MaxAltBlocks", &opts) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return 0, returnedError + } + return returnedValues[0].Interface().(uint8), nil } func (b BlockManagerStruct) SortedProposedBlockIds(client *ethclient.Client, arg0 uint32, arg1 *big.Int) (uint32, error) { blockManager, opts := UtilsInterface.GetBlockManagerWithOpts(client) - return blockManager.SortedProposedBlockIds(&opts, arg0, arg1) + returnedValues := InvokeFunctionWithTimeout(blockManager, "SortedProposedBlockIds", &opts, arg0, arg1) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return 0, returnedError + } + return returnedValues[0].Interface().(uint32), nil +} + +func (b BlockManagerStruct) GetEpochLastProposed(client *ethclient.Client, stakerId uint32) (uint32, error) { + blockManager, opts := UtilsInterface.GetBlockManagerWithOpts(client) + returnedValues := InvokeFunctionWithTimeout(blockManager, "EpochLastProposed", &opts, stakerId) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return 0, returnedError + } + return returnedValues[0].Interface().(uint32), nil } func (s StakeManagerStruct) GetStakerId(client *ethclient.Client, address common.Address) (uint32, error) { stakeManager, opts := UtilsInterface.GetStakeManagerWithOpts(client) - return stakeManager.GetStakerId(&opts, address) + returnedValues := InvokeFunctionWithTimeout(stakeManager, "GetStakerId", &opts, address) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return 0, returnedError + } + return returnedValues[0].Interface().(uint32), nil } func (s StakeManagerStruct) GetNumStakers(client *ethclient.Client) (uint32, error) { stakeManager, opts := UtilsInterface.GetStakeManagerWithOpts(client) - return stakeManager.GetNumStakers(&opts) + returnedValues := InvokeFunctionWithTimeout(stakeManager, "GetNumStakers", &opts) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return 0, returnedError + } + return returnedValues[0].Interface().(uint32), nil } func (s StakeManagerStruct) MinSafeRazor(client *ethclient.Client) (*big.Int, error) { stakeManager, opts := UtilsInterface.GetStakeManagerWithOpts(client) - return stakeManager.MinSafeRazor(&opts) + returnedValues := InvokeFunctionWithTimeout(stakeManager, "MinSafeRazor", &opts) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return nil, returnedError + } + return returnedValues[0].Interface().(*big.Int), nil } func (s StakeManagerStruct) Locks(client *ethclient.Client, address common.Address, address1 common.Address, lockType uint8) (coretypes.Locks, error) { stakeManager, opts := UtilsInterface.GetStakeManagerWithOpts(client) - return stakeManager.Locks(&opts, address, address1, lockType) + returnedValues := InvokeFunctionWithTimeout(stakeManager, "Locks", &opts, address, address1, lockType) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return coretypes.Locks{}, returnedError + } + locks := returnedValues[0].Interface().(struct { + Amount *big.Int + UnlockAfter *big.Int + }) + return locks, nil } func (s StakeManagerStruct) MaxCommission(client *ethclient.Client) (uint8, error) { stakeManager, opts := UtilsInterface.GetStakeManagerWithOpts(client) - return stakeManager.MaxCommission(&opts) + returnedValues := InvokeFunctionWithTimeout(stakeManager, "MaxCommission", &opts) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return 0, returnedError + } + return returnedValues[0].Interface().(uint8), nil } func (s StakeManagerStruct) EpochLimitForUpdateCommission(client *ethclient.Client) (uint16, error) { stakeManager, opts := UtilsInterface.GetStakeManagerWithOpts(client) - return stakeManager.EpochLimitForUpdateCommission(&opts) + returnedValues := InvokeFunctionWithTimeout(stakeManager, "EpochLimitForUpdateCommission", &opts) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return 0, returnedError + } + return returnedValues[0].Interface().(uint16), nil } func (s StakeManagerStruct) GetStaker(client *ethclient.Client, stakerId uint32) (bindings.StructsStaker, error) { stakeManager, opts := UtilsInterface.GetStakeManagerWithOpts(client) - return stakeManager.GetStaker(&opts, stakerId) + returnedValues := InvokeFunctionWithTimeout(stakeManager, "GetStaker", &opts, stakerId) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return bindings.StructsStaker{}, returnedError + } + return returnedValues[0].Interface().(bindings.StructsStaker), nil } func (a AssetManagerStruct) GetNumCollections(client *ethclient.Client) (uint16, error) { collectionManager, opts := UtilsInterface.GetCollectionManagerWithOpts(client) - return collectionManager.GetNumCollections(&opts) + returnedValues := InvokeFunctionWithTimeout(collectionManager, "GetNumCollections", &opts) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return 0, returnedError + } + return returnedValues[0].Interface().(uint16), nil } func (a AssetManagerStruct) GetNumActiveCollections(client *ethclient.Client) (uint16, error) { collectionManager, opts := UtilsInterface.GetCollectionManagerWithOpts(client) - return collectionManager.GetNumActiveCollections(&opts) + returnedValues := InvokeFunctionWithTimeout(collectionManager, "GetNumActiveCollections", &opts) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return 0, returnedError + } + return returnedValues[0].Interface().(uint16), nil } func (a AssetManagerStruct) GetActiveCollections(client *ethclient.Client) ([]uint16, error) { collectionManager, opts := UtilsInterface.GetCollectionManagerWithOpts(client) - return collectionManager.GetActiveCollections(&opts) + returnedValues := InvokeFunctionWithTimeout(collectionManager, "GetActiveCollections", &opts) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return nil, returnedError + } + return returnedValues[0].Interface().([]uint16), nil } func (a AssetManagerStruct) Jobs(client *ethclient.Client, id uint16) (bindings.StructsJob, error) { collectionManager, opts := UtilsInterface.GetCollectionManagerWithOpts(client) - return collectionManager.Jobs(&opts, id) + returnedValues := InvokeFunctionWithTimeout(collectionManager, "Jobs", &opts, id) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return bindings.StructsJob{}, returnedError + } + job := returnedValues[0].Interface().(struct { + Id uint16 + SelectorType uint8 + Weight uint8 + Power int8 + Name string + Selector string + Url string + }) + return job, nil } func (v VoteManagerStruct) Commitments(client *ethclient.Client, stakerId uint32) (coretypes.Commitment, error) { voteManager, opts := UtilsInterface.GetVoteManagerWithOpts(client) - return voteManager.Commitments(&opts, stakerId) + returnedValues := InvokeFunctionWithTimeout(voteManager, "Commitments", &opts, stakerId) + returnedError := CheckIfAnyError(returnedValues) + if returnedValues != nil { + return coretypes.Commitment{}, returnedError + } + commitment := returnedValues[0].Interface().(struct { + Epoch uint32 + CommitmentHash [32]byte + }) + return commitment, nil } func (v VoteManagerStruct) GetVoteValue(client *ethclient.Client, epoch uint32, stakerId uint32, medianIndex uint16) (*big.Int, error) { voteManager, opts := UtilsInterface.GetVoteManagerWithOpts(client) - return voteManager.GetVoteValue(&opts, epoch, stakerId, medianIndex) + returnedValues := InvokeFunctionWithTimeout(voteManager, "GetVoteValue", &opts, epoch, stakerId, medianIndex) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return nil, returnedError + } + return returnedValues[0].Interface().(*big.Int), nil } func (v VoteManagerStruct) GetInfluenceSnapshot(client *ethclient.Client, epoch uint32, stakerId uint32) (*big.Int, error) { voteManager, opts := UtilsInterface.GetVoteManagerWithOpts(client) - return voteManager.GetInfluenceSnapshot(&opts, epoch, stakerId) + returnedValues := InvokeFunctionWithTimeout(voteManager, "GetInfluenceSnapshot", &opts, epoch, stakerId) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return nil, returnedError + } + return returnedValues[0].Interface().(*big.Int), nil } func (v VoteManagerStruct) GetStakeSnapshot(client *ethclient.Client, epoch uint32, stakerId uint32) (*big.Int, error) { voteManager, opts := UtilsInterface.GetVoteManagerWithOpts(client) - return voteManager.GetStakeSnapshot(&opts, epoch, stakerId) + returnedValues := InvokeFunctionWithTimeout(voteManager, "GetStakeSnapshot", &opts, epoch, stakerId) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return nil, returnedError + } + return returnedValues[0].Interface().(*big.Int), nil } func (v VoteManagerStruct) GetTotalInfluenceRevealed(client *ethclient.Client, epoch uint32, medianIndex uint16) (*big.Int, error) { voteManager, opts := UtilsInterface.GetVoteManagerWithOpts(client) - return voteManager.GetTotalInfluenceRevealed(&opts, epoch, medianIndex) + returnedValues := InvokeFunctionWithTimeout(voteManager, "GetTotalInfluenceRevealed", &opts, epoch, medianIndex) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return nil, returnedError + } + return returnedValues[0].Interface().(*big.Int), nil } func (v VoteManagerStruct) GetEpochLastCommitted(client *ethclient.Client, stakerId uint32) (uint32, error) { voteManager, opts := UtilsInterface.GetVoteManagerWithOpts(client) - return voteManager.GetEpochLastCommitted(&opts, stakerId) + returnedValues := InvokeFunctionWithTimeout(voteManager, "GetEpochLastCommitted", &opts, stakerId) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return 0, returnedError + } + return returnedValues[0].Interface().(uint32), nil } func (v VoteManagerStruct) GetEpochLastRevealed(client *ethclient.Client, stakerId uint32) (uint32, error) { voteManager, opts := UtilsInterface.GetVoteManagerWithOpts(client) - return voteManager.GetEpochLastRevealed(&opts, stakerId) + returnedValues := InvokeFunctionWithTimeout(voteManager, "GetEpochLastRevealed", &opts, stakerId) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return 0, returnedError + } + return returnedValues[0].Interface().(uint32), nil } func (b BindingsStruct) NewCollectionManager(address common.Address, client *ethclient.Client) (*bindings.CollectionManager, error) { @@ -295,31 +556,67 @@ func (i IOStruct) ReadAll(body io.ReadCloser) ([]byte, error) { } func (c ClientStruct) TransactionReceipt(client *ethclient.Client, ctx context.Context, txHash common.Hash) (*types.Receipt, error) { - return client.TransactionReceipt(ctx, txHash) + returnedValues := InvokeFunctionWithTimeout(client, "TransactionReceipt", ctx, txHash) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return &types.Receipt{}, returnedError + } + return returnedValues[0].Interface().(*types.Receipt), nil } func (c ClientStruct) BalanceAt(client *ethclient.Client, ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error) { - return client.BalanceAt(ctx, account, blockNumber) + returnedValues := InvokeFunctionWithTimeout(client, "BalanceAt", ctx, account, blockNumber) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return nil, returnedError + } + return returnedValues[0].Interface().(*big.Int), nil } func (c ClientStruct) HeaderByNumber(client *ethclient.Client, ctx context.Context, number *big.Int) (*types.Header, error) { - return client.HeaderByNumber(ctx, number) + returnedValues := InvokeFunctionWithTimeout(client, "HeaderByNumber", ctx, number) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return &types.Header{}, returnedError + } + return returnedValues[0].Interface().(*types.Header), nil } -func (c ClientStruct) PendingNonceAt(client *ethclient.Client, ctx context.Context, account common.Address) (uint64, error) { - return client.PendingNonceAt(ctx, account) +func (c ClientStruct) NonceAt(client *ethclient.Client, ctx context.Context, account common.Address) (uint64, error) { + var blockNumber *big.Int + returnedValues := InvokeFunctionWithTimeout(client, "NonceAt", ctx, account, blockNumber) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return 0, returnedError + } + return returnedValues[0].Interface().(uint64), nil } func (c ClientStruct) SuggestGasPrice(client *ethclient.Client, ctx context.Context) (*big.Int, error) { - return client.SuggestGasPrice(ctx) + returnedValues := InvokeFunctionWithTimeout(client, "SuggestGasPrice", ctx) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return nil, returnedError + } + return returnedValues[0].Interface().(*big.Int), nil } func (c ClientStruct) EstimateGas(client *ethclient.Client, ctx context.Context, msg ethereum.CallMsg) (uint64, error) { - return client.EstimateGas(ctx, msg) + returnedValues := InvokeFunctionWithTimeout(client, "EstimateGas", ctx, msg) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return 0, returnedError + } + return returnedValues[0].Interface().(uint64), nil } func (c ClientStruct) FilterLogs(client *ethclient.Client, ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) { - return client.FilterLogs(ctx, q) + returnedValues := InvokeFunctionWithTimeout(client, "FilterLogs", ctx, q) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return []types.Log{}, returnedError + } + return returnedValues[0].Interface().([]types.Log), nil } func (b BufioStruct) NewScanner(r io.Reader) *bufio.Scanner { @@ -327,7 +624,12 @@ func (b BufioStruct) NewScanner(r io.Reader) *bufio.Scanner { } func (c CoinStruct) BalanceOf(coinContract *bindings.RAZOR, opts *bind.CallOpts, account common.Address) (*big.Int, error) { - return coinContract.BalanceOf(opts, account) + returnedValues := InvokeFunctionWithTimeout(coinContract, "BalanceOf", opts, account) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return nil, returnedError + } + return returnedValues[0].Interface().(*big.Int), nil } func (a ABIStruct) Parse(reader io.Reader) (abi.ABI, error) { @@ -351,7 +653,12 @@ func (b BindStruct) NewKeyedTransactorWithChainID(key *ecdsa.PrivateKey, chainID } func (s StakedTokenStruct) BalanceOf(stakedToken *bindings.StakedToken, callOpts *bind.CallOpts, address common.Address) (*big.Int, error) { - return stakedToken.BalanceOf(callOpts, address) + returnedValues := InvokeFunctionWithTimeout(stakedToken, "BalanceOf", callOpts, address) + returnedError := CheckIfAnyError(returnedValues) + if returnedError != nil { + return nil, returnedError + } + return returnedValues[0].Interface().(*big.Int), nil } func (r RetryStruct) RetryAttempts(numberOfAttempts uint) retry.Option {