From 6254410cdfc28a73211083cd84422029dc454be2 Mon Sep 17 00:00:00 2001 From: ak88 Date: Fri, 14 Nov 2025 10:18:28 +0100 Subject: [PATCH 01/25] calculator --- .../Nethermind.Xdc/Spec/XdcReleaseSpec.cs | 2 + .../Nethermind.Xdc/XdcRewardCalculator.cs | 308 ++++++++++++++++++ 2 files changed, 310 insertions(+) create mode 100644 src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs diff --git a/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs b/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs index c793d675bc2..0b8f3a4dc0d 100644 --- a/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs @@ -30,6 +30,7 @@ public class XdcReleaseSpec : ReleaseSpec, IXdcReleaseSpec public List V2Configs { get; set; } = new List(); public Address[] GenesisMasterNodes { get; set; } + public Address FoundationWallet { get; set; } public void ApplyV2Config(ulong round) { @@ -96,6 +97,7 @@ public interface IXdcReleaseSpec : IReleaseSpec public int MinimumSigningTx { get; set; } // Signing txs that a node needs to produce to get out of penalty, after `LimitPenaltyEpoch` public List V2Configs { get; set; } Address[] GenesisMasterNodes { get; set; } + Address FoundationWallet { get; set; } public void ApplyV2Config(ulong round); } diff --git a/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs b/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs new file mode 100644 index 00000000000..ea1621efeb9 --- /dev/null +++ b/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs @@ -0,0 +1,308 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Consensus.Rewards; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Specs; +using Nethermind.Int256; +using Nethermind.Logging; +using Nethermind.Xdc.Spec; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; + +namespace Nethermind.Xdc +{ + /// + /// Rewards are distributed at epoch boundaries (every 900 blocks) based on: + /// - Masternode signature count during the epoch + /// - 40% infrastructure / 50% staking / 10% foundation split + /// - Proportional distribution among delegators based on stake + /// + public class XdcRewardCalculator( + IEpochSwitchManager epochSwitchManager, + ISpecProvider specProvider, + ILogManager logManager, + IXdcSignatureTracker signatureTracker, + IXdcStakingManager stakingManager) : IRewardCalculator + { + private readonly ILogger logger = logManager?.GetClassLogger() ?? NullLogger.Instance; + + // Reward amount per epoch (5000 XDC in Wei) + // 1 XDC = 10^18 Wei, so 5000 XDC = 5000 * 10^18 Wei + private static readonly UInt256 EPOCH_REWARD = UInt256.Parse("5000000000000000000000"); + + /// + /// Calculates block rewards according to XDPoS consensus rules. + /// + /// For XDPoS, rewards are only distributed at epoch checkpoints (blocks where number % 900 == 0). + /// At these checkpoints, rewards are calculated based on masternode signature counts during + /// the previous epoch and distributed according to the 40/50/10 split model. + /// + /// The block to calculate rewards for + /// Array of BlockReward objects for all reward recipients + public BlockReward[] CalculateRewards(Block block) + { + if (block is null) + throw new ArgumentNullException(nameof(block)); + if (block.Header is not XdcBlockHeader xdcHeader) + throw new InvalidOperationException("Only supports XDC headers"); + + IXdcReleaseSpec spec = specProvider.GetXdcSpec(xdcHeader, xdcHeader.ExtraConsensusData.BlockRound); + + if (!epochSwitchManager.IsEpochSwitchAtBlock(xdcHeader)) + { + // Non-checkpoint blocks don't trigger reward distribution in XDPoS + // The block producer still gets transaction fees, but no block reward + if (logger.IsTrace) logger.Trace($"Block {block.Number} is not an epoch switch, no rewards distributed"); + return Array.Empty(); + } + + // Calculate the epoch that just completed + long completedEpoch = (block.Number / spec.EpochLength) - 1; + long epochStartBlock = completedEpoch * spec.EpochLength + 1; + long epochEndBlock = (completedEpoch + 1) * spec.EpochLength; + + var epochNumber = spec.SwitchEpoch + (long)xdcHeader.ExtraConsensusData.BlockRound / spec.EpochLength; + + var originReward = spec.BlockReward * Unit.Ether; + try + { + // Get signature counts for all masternodes in the completed epoch + var signatureCounts = signatureTracker.GetSignatureCounts(epochStartBlock, epochEndBlock); + + if (signatureCounts == null || signatureCounts.Count == 0) + { + logger.Warn($"No signature data available for epoch {completedEpoch}"); + return Array.Empty(); + } + + // Calculate total signatures across all masternodes + long totalSignatures = signatureCounts.Values.Sum(); + + if (totalSignatures == 0) + { + logger.Warn($"Total signatures for epoch {completedEpoch} is zero"); + return Array.Empty(); + } + + // Calculate and distribute rewards + var rewards = new List(); + + foreach (var masternodeSignature in signatureCounts) + { + Address masternodeAddress = masternodeSignature.Key; + long signatureCount = masternodeSignature.Value; + + // Calculate this masternode's proportional share of the epoch reward + // Formula: (masternode_signatures / total_signatures) * EPOCH_REWARD + UInt256 masternodeBaseReward = CalculateProportionalReward( + signatureCount, + totalSignatures, + EPOCH_REWARD + ); + + // Split the reward according to XDPoS distribution model + var (infraReward, stakingPool, foundationReward) = SplitReward(masternodeBaseReward); + + // 1. Infrastructure reward (40%) goes directly to masternode operator + rewards.Add(new BlockReward(masternodeAddress, infraReward, BlockRewardType.Block)); + + // 2. Foundation reward (10%) goes to XDC Foundation + rewards.Add(new BlockReward(spec.FoundationWallet, foundationReward, BlockRewardType.External)); + + // 3. Staking reward (50%) is distributed among delegators proportionally + var delegatorRewards = DistributeStakingRewards( + masternodeAddress, + stakingPool, + block.Number + ); + + rewards.AddRange(delegatorRewards); + } + + return rewards.ToArray(); + } + catch (Exception ex) + { + logger.Error($"Error calculating XDPoS rewards for block {block.Number}", ex); + throw; + } + } + + /// + /// Calculates a proportional reward based on the number of signatures. + /// Uses UInt256 arithmetic to maintain precision with large Wei values. + /// + /// Formula: (signatureCount / totalSignatures) * totalReward + /// + private UInt256 CalculateProportionalReward( + long signatureCount, + long totalSignatures, + UInt256 totalReward) + { + if (signatureCount <= 0 || totalSignatures <= 0) + { + return UInt256.Zero; + } + + // Convert to UInt256 for precision + UInt256 signatures = (UInt256)signatureCount; + UInt256 total = (UInt256)totalSignatures; + + // Calculate: (signatures * totalReward) / total + // Order of operations matters to maintain precision + UInt256 numerator = signatures * totalReward; + UInt256 reward = numerator / total; + + return reward; + } + + /// + /// Splits a masternode's base reward according to the XDPoS distribution model: + /// - 40% Infrastructure (masternode operator) + /// - 50% Staking (delegators) + /// - 10% Foundation (XDC Foundation) + /// + private (UInt256 infrastructure, UInt256 staking, UInt256 foundation) SplitReward(UInt256 baseReward) + { + // Calculate each component + // Using integer division with appropriate scaling to avoid precision loss + + // 40% for infrastructure + UInt256 infrastructure = (baseReward * 40) / 100; + + // 50% for staking pool + UInt256 staking = (baseReward * 50) / 100; + + // 10% for foundation + UInt256 foundation = (baseReward * 10) / 100; + + // Handle any rounding remainder by adding it to infrastructure + UInt256 allocated = infrastructure + staking + foundation; + if (allocated < baseReward) + { + infrastructure += (baseReward - allocated); + } + + return (infrastructure, staking, foundation); + } + + /// + /// Distributes the staking reward pool among all delegators who have staked with this masternode. + /// Each delegator receives a proportion based on their stake amount relative to the total stake. + /// + /// Only delegators who were active at the checkpoint block receive rewards. + /// + private List DistributeStakingRewards( + Address masternodeAddress, + UInt256 stakingPool, + long checkpointBlock) + { + var delegatorRewards = new List(); + + if (stakingPool.IsZero) + { + return delegatorRewards; + } + + // Get all active stakes for this masternode at the checkpoint + var stakes = stakingManager.GetActiveStakes(masternodeAddress, checkpointBlock); + + if (stakes == null || stakes.Count == 0) + { + // No delegators, staking pool could be reallocated to infrastructure + // or left undistributed depending on implementation choice + if (logger.IsDebug) + { + logger.Debug($"No active delegators for masternode {masternodeAddress}, staking pool: {stakingPool} Wei"); + } + return delegatorRewards; + } + + // Calculate total stake across all delegators + UInt256 totalStake = UInt256.Zero; + foreach (var stake in stakes) + { + totalStake += stake.Amount; + } + + if (totalStake.IsZero) + { + logger.Warn($"Total stake is zero for masternode {masternodeAddress}"); + return delegatorRewards; + } + + // Distribute rewards proportionally to each delegator + foreach (var stake in stakes) + { + // Formula: (delegator_stake / total_stake) * staking_pool + UInt256 delegatorReward = (stake.Amount * stakingPool) / totalStake; + + if (!delegatorReward.IsZero) + { + delegatorRewards.Add(new BlockReward( + stake.DelegatorAddress, + delegatorReward, + BlockRewardType.External + )); + } + } + + return delegatorRewards; + } + + public UInt256 RewardInflation(IXdcReleaseSpec spec, UInt256 chainReward, long number, long blockPerYear) + { + UInt256 reward = chainReward; + if (blockPerYear * 2 <= number && number < blockPerYear * 5) + { + reward = chainReward / 2; + } + if (blockPerYear * 5 <= number) + { + reward = chainReward / 4; + } + return reward; + } + } + + public class StakePosition + { + public Address DelegatorAddress { get; set; } + public UInt256 Amount { get; set; } + public long StakedAtBlock { get; set; } + + public StakePosition(Address delegator, UInt256 amount, long stakedAt) + { + DelegatorAddress = delegator; + Amount = amount; + StakedAtBlock = stakedAt; + } + } + + public interface IXdcSignatureTracker + { + /// + /// Gets the signature count for each masternode between the specified block range. + /// + /// Start of the range (inclusive) + /// End of the range (inclusive) + /// Dictionary mapping masternode address to signature count + Dictionary GetSignatureCounts(long startBlock, long endBlock); + } + + public interface IXdcStakingManager + { + /// + /// Gets all active stake positions for a masternode at a specific block. + /// Only returns stakes that were active (not withdrawn) at the checkpoint. + /// + /// The masternode address + /// The block number to check stakes at + /// List of active stake positions + List GetActiveStakes(Address masternodeAddress, long atBlock); + } +} From 6dd5ba63b29ae1ab73cbe969a8b8360b6ea3a332 Mon Sep 17 00:00:00 2001 From: ak88 Date: Tue, 18 Nov 2025 00:18:02 +0100 Subject: [PATCH 02/25] state reader --- .../Nethermind.Xdc/Spec/XdcReleaseSpec.cs | 2 + .../State/MasternodeVotingContract.cs | 15 ++++ .../Nethermind.Xdc/XdcContractStateReader.cs | 72 +++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 src/Nethermind/Nethermind.Xdc/State/MasternodeVotingContract.cs create mode 100644 src/Nethermind/Nethermind.Xdc/XdcContractStateReader.cs diff --git a/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs b/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs index c793d675bc2..7b207f6b208 100644 --- a/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs @@ -31,6 +31,8 @@ public class XdcReleaseSpec : ReleaseSpec, IXdcReleaseSpec public Address[] GenesisMasterNodes { get; set; } + public Address MasternodeVotingContract { get; set; } + public void ApplyV2Config(ulong round) { V2ConfigParams configParams = GetConfigAtRound(V2Configs, round); diff --git a/src/Nethermind/Nethermind.Xdc/State/MasternodeVotingContract.cs b/src/Nethermind/Nethermind.Xdc/State/MasternodeVotingContract.cs new file mode 100644 index 00000000000..1bd19f7973e --- /dev/null +++ b/src/Nethermind/Nethermind.Xdc/State/MasternodeVotingContract.cs @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Blockchain.Contracts; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Nethermind.Xdc.State; +internal class MasternodeVotingContract : Contract +{ + +} diff --git a/src/Nethermind/Nethermind.Xdc/XdcContractStateReader.cs b/src/Nethermind/Nethermind.Xdc/XdcContractStateReader.cs new file mode 100644 index 00000000000..524ea583a38 --- /dev/null +++ b/src/Nethermind/Nethermind.Xdc/XdcContractStateReader.cs @@ -0,0 +1,72 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Microsoft.AspNetCore.Mvc; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Specs; +using Nethermind.Evm.State; +using Nethermind.Int256; +using Nethermind.Serialization.Rlp; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Nethermind.Xdc; + +internal class XdcContractStateReader(IWorldState worldState, ISpecProvider specProvider) +{ + + public Address[] GetCandidates(XdcBlockHeader header) + { + var spec = specProvider.GetXdcSpec(header, header.ExtraConsensusData.BlockRound); + var variableSlot = CandidateContractSlots.Candidates; + Span input = [(byte)variableSlot]; + var slot = new UInt256(Keccak.Compute(input).Bytes); + using var state = worldState.BeginScope(header); + ReadOnlySpan storageCell = worldState.Get(new StorageCell(spec.MasternodeVotingContract, slot)); + var length = new UInt256(storageCell); + Address[] candidates = new Address[(ulong)length]; + for (int i = 0; i < length; i++) + { + var key = CalculateArrayKey(slot, (ulong)i, 1); + candidates[i] = new Address(worldState.Get(new StorageCell(spec.MasternodeVotingContract, key))); + } + return candidates; + } + + private UInt256 CalculateArrayKey(UInt256 slot, ulong index, ulong size) + { + return slot + new UInt256(index * size); + } + + public UInt256 GetCandidateStake(Address candidate) + { + var variableSlot = CandidateContractSlots.ValidatorsState; + + } + + private enum CandidateContractSlots : byte + { + WithdrawsState, + ValidatorsState, + Voters, + KYCString, + InvalidKYCCount, + HasVotedInvalid, + OwnerToCandidate, + Owners, + Candidates, + CandidateCount, + OwnerCount, + MinCandidateCap, + MinVoterCap, + MaxValidatorNumber, + CandidateWithdrawDelay, + VoterWithdrawDelay + } +} + + From f7e2c2e227e5df558ece38610e4be5be22cd207c Mon Sep 17 00:00:00 2001 From: ak88 Date: Tue, 18 Nov 2025 17:26:53 +0100 Subject: [PATCH 03/25] masternode voting contract --- .../Nethermind.Xdc/Contracts/ContractData.cs | 19 ++++ .../Contracts/IMasternodeVotingContract.cs | 12 +++ .../Contracts/MasternodeVotingContract.cs | 96 +++++++++++++++++++ .../Nethermind.Xdc/Spec/XdcReleaseSpec.cs | 1 + .../State/MasternodeVotingContract.cs | 15 --- .../Nethermind.Xdc/XdcContractStateReader.cs | 72 -------------- 6 files changed, 128 insertions(+), 87 deletions(-) create mode 100644 src/Nethermind/Nethermind.Xdc/Contracts/ContractData.cs create mode 100644 src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs create mode 100644 src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs delete mode 100644 src/Nethermind/Nethermind.Xdc/State/MasternodeVotingContract.cs delete mode 100644 src/Nethermind/Nethermind.Xdc/XdcContractStateReader.cs diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/ContractData.cs b/src/Nethermind/Nethermind.Xdc/Contracts/ContractData.cs new file mode 100644 index 00000000000..0c08f0caeea --- /dev/null +++ b/src/Nethermind/Nethermind.Xdc/Contracts/ContractData.cs @@ -0,0 +1,19 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Core.Extensions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Nethermind.Xdc.Contracts; +internal static class ContractData +{ + // XDCValidatorABI is the input ABI used to generate the binding from. + public static string XDCValidatorABI() => "[{\"constant\":false,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"propose\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"owners\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"},{\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"unvote\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCandidates\",\"outputs\":[{\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"ownerCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"address\"}],\"name\":\"hasVotedInvalid\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_blockNumber\",\"type\":\"uint256\"}],\"name\":\"getWithdrawCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownerToCandidate\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"getVoters\",\"outputs\":[{\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getWithdrawBlockNumbers\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"},{\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"getVoterCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"getLatestKYC\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"candidates\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_blockNumber\",\"type\":\"uint256\"},{\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"getCandidateCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_invalidCandidate\",\"type\":\"address\"}],\"name\":\"invalidPercent\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"KYCString\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"vote\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"invalidKYCCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"candidateCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"voterWithdrawDelay\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"resign\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"getCandidateOwner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"getHashCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxValidatorNumber\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"candidateWithdrawDelay\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"isCandidate\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"minCandidateCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getOwnerCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_invalidCandidate\",\"type\":\"address\"}],\"name\":\"voteInvalidKYC\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"kychash\",\"type\":\"string\"}],\"name\":\"uploadKYC\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"minVoterCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_candidates\",\"type\":\"address[]\"},{\"name\":\"_caps\",\"type\":\"uint256[]\"},{\"name\":\"_firstOwner\",\"type\":\"address\"},{\"name\":\"_minCandidateCap\",\"type\":\"uint256\"},{\"name\":\"_minVoterCap\",\"type\":\"uint256\"},{\"name\":\"_maxValidatorNumber\",\"type\":\"uint256\"},{\"name\":\"_candidateWithdrawDelay\",\"type\":\"uint256\"},{\"name\":\"_voterWithdrawDelay\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_voter\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_candidate\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"Vote\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_voter\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_candidate\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"Unvote\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_candidate\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"Propose\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"Resign\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_blockNumber\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"kycHash\",\"type\":\"string\"}],\"name\":\"UploadedKYC\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_masternodeOwner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_masternodes\",\"type\":\"address[]\"}],\"name\":\"InvalidatedNode\",\"type\":\"event\"}]" + + // XDCValidatorBin is the compiled bytecode used for deploying new contracts. + public static byte[] XDCValidatorBin() => Bytes.FromHexString("0x606060405260006009556000600a5534156200001a57600080fd5b60405162003dcc38038062003dcc83398101604052808051820191906020018051820191906020018051906020019091908051906020019091908051906020019091908051906020019091908051906020019091908051906020019091905050600085600b8190555084600c8190555083600d8190555082600e8190555081600f81905550885160098190555060078054806001018281620000bd9190620004f1565b9160005260206000209001600089909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600a60008154809291906001019190505550600090505b8851811015620004e25760088054806001018281620001439190620004f1565b916000526020600020900160008b848151811015156200015f57fe5b90602001906020020151909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506060604051908101604052808873ffffffffffffffffffffffffffffffffffffffff1681526020016001151581526020018983815181101515620001ea57fe5b90602001906020020151815250600160008b848151811015156200020a57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548160ff02191690831515021790555060408201518160010155905050600260008a83815181101515620002d557fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816200032d9190620004f1565b9160005260206000209001600089909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281620003cf9190620004f1565b916000526020600020900160008b84815181101515620003eb57fe5b90602001906020020151909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600b54600160008b848151811015156200044c57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550808060010191505062000123565b50505050505050505062000548565b8154818355818115116200051b578183600052602060002091820191016200051a919062000520565b5b505050565b6200054591905b808211156200054157600081600090555060010162000527565b5090565b90565b61387480620005586000396000f300606060405260043610610196576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063012679511461019b578063025e7c27146101c957806302aa9be21461022c57806306a49fce1461026e5780630db02622146102d85780630e3e4fb81461030157806315febd68146103715780632a3640b1146103a85780632d15cc041461042a5780632f9c4bba146104b8578063302b687214610522578063326586521461058e5780633477ee2e14610640578063441a3e70146106a357806358e7525f146106cf5780635b860d271461071c5780635b9cd8cc146107695780636dd7d8ea1461082457806372e44a3814610852578063a9a981a31461089f578063a9ff959e146108c8578063ae6e43f5146108f1578063b642facd1461092a578063c45607df146109a3578063d09f1ab4146109f0578063d161c76714610a19578063d51b9e9314610a42578063d55b7dff14610a93578063ef18374a14610abc578063f2ee3c7d14610ae5578063f5c9512514610b1e578063f8ac9dd514610b4c575b600080fd5b6101c7600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610b75565b005b34156101d457600080fd5b6101ea60048080359060200190919050506111fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561023757600080fd5b61026c600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061123b565b005b341561027957600080fd5b610281611796565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102c45780820151818401526020810190506102a9565b505050509050019250505060405180910390f35b34156102e357600080fd5b6102eb61182a565b6040518082815260200191505060405180910390f35b341561030c57600080fd5b610357600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611830565b604051808215151515815260200191505060405180910390f35b341561037c57600080fd5b610392600480803590602001909190505061185f565b6040518082815260200191505060405180910390f35b34156103b357600080fd5b6103e8600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506118bb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561043557600080fd5b610461600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611909565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156104a4578082015181840152602081019050610489565b505050509050019250505060405180910390f35b34156104c357600080fd5b6104cb6119dc565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561050e5780820151818401526020810190506104f3565b505050509050019250505060405180910390f35b341561052d57600080fd5b610578600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611a79565b6040518082815260200191505060405180910390f35b341561059957600080fd5b6105c5600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611b03565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156106055780820151818401526020810190506105ea565b50505050905090810190601f1680156106325780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561064b57600080fd5b6106616004808035906020019091905050611da2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156106ae57600080fd5b6106cd6004808035906020019091908035906020019091905050611de1565b005b34156106da57600080fd5b610706600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061208d565b6040518082815260200191505060405180910390f35b341561072757600080fd5b610753600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506120d9565b6040518082815260200191505060405180910390f35b341561077457600080fd5b6107a9600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506121a1565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156107e95780820151818401526020810190506107ce565b50505050905090810190601f1680156108165780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610850600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061226a565b005b341561085d57600080fd5b610889600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612653565b6040518082815260200191505060405180910390f35b34156108aa57600080fd5b6108b261266b565b6040518082815260200191505060405180910390f35b34156108d357600080fd5b6108db612671565b6040518082815260200191505060405180910390f35b34156108fc57600080fd5b610928600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612677565b005b341561093557600080fd5b610961600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612c36565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156109ae57600080fd5b6109da600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612ca2565b6040518082815260200191505060405180910390f35b34156109fb57600080fd5b610a03612cee565b6040518082815260200191505060405180910390f35b3415610a2457600080fd5b610a2c612cf4565b6040518082815260200191505060405180910390f35b3415610a4d57600080fd5b610a79600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612cfa565b604051808215151515815260200191505060405180910390f35b3415610a9e57600080fd5b610aa6612d53565b6040518082815260200191505060405180910390f35b3415610ac757600080fd5b610acf612d59565b6040518082815260200191505060405180910390f35b3415610af057600080fd5b610b1c600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612d63565b005b3415610b2957600080fd5b610b4a600480803590602001908201803590602001919091929050506134f1565b005b3415610b5757600080fd5b610b5f6135f0565b6040518082815260200191505060405180910390f35b6000600b543410151515610b8857600080fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050141580610c1c57506000600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050115b1515610c2757600080fd5b81600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff16151515610c8457600080fd5b610cd934600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101546135f690919063ffffffff16565b915060088054806001018281610cef919061362d565b9160005260206000209001600085909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506060604051908101604052803373ffffffffffffffffffffffffffffffffffffffff16815260200160011515815260200183815250600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548160ff02191690831515021790555060408201518160010155905050610eb834600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546135f690919063ffffffff16565b600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610f5160016009546135f690919063ffffffff16565b6009819055506000600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905014156110185760078054806001018281610fb6919061362d565b9160005260206000209001600033909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600a600081548092919060010191905055505b600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281611069919061362d565b9160005260206000209001600085909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281611109919061362d565b9160005260206000209001600033909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550507f7635f1d87b47fba9f2b09e56eb4be75cca030e0cb179c1602ac9261d39a8f5c1338434604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a1505050565b60078181548110151561120b57fe5b90600052602060002090016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000828280600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156112cd57600080fd5b3373ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561140657600b546113f882600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461361490919063ffffffff16565b1015151561140557600080fd5b5b61145b84600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015461361490919063ffffffff16565b600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018190555061153384600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461361490919063ffffffff16565b600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506115cb43600f546135f690919063ffffffff16565b9250611632846000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000868152602001908152602001600020546135f690919063ffffffff16565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000858152602001908152602001600020819055506000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010180548060010182816116db9190613659565b9160005260206000209001600085909190915055507faa0e554f781c3c3b2be110a0557f260f11af9a8aa2c64bc1e7a31dbb21e32fa2338686604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a15050505050565b61179e613685565b600880548060200260200160405190810160405280929190818152602001828054801561182057602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116117d6575b5050505050905090565b600a5481565b60056020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60008060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000838152602001908152602001600020549050919050565b6006602052816000526040600020818154811015156118d657fe5b90600052602060002090016000915091509054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611911613685565b600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156119d057602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311611986575b50505050509050919050565b6119e4613699565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101805480602002602001604051908101604052809291908181526020018280548015611a6f57602002820191906000526020600020905b815481526020019060010190808311611a5b575b5050505050905090565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b611b0b6136ad565b611b1482612cfa565b15611c655760036000611b2684612c36565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600160036000611b6f86612c36565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905003815481101515611bba57fe5b90600052602060002090018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611c595780601f10611c2e57610100808354040283529160200191611c59565b820191906000526020600020905b815481529060010190602001808311611c3c57829003601f168201915b50505050509050611d9d565b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905003815481101515611cf657fe5b90600052602060002090018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611d955780601f10611d6a57610100808354040283529160200191611d95565b820191906000526020600020905b815481529060010190602001808311611d7857829003601f168201915b505050505090505b919050565b600881815481101515611db157fe5b90600052602060002090016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008282600082111515611df457600080fd5b814310151515611e0357600080fd5b60008060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001600084815260200190815260200160002054111515611e6457600080fd5b816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010182815481101515611eb357fe5b906000526020600020900154141515611ecb57600080fd5b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008681526020019081526020016000205492506000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000868152602001908152602001600020600090556000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010184815481101515611fc457fe5b9060005260206000209001600090553373ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f19350505050151561201357600080fd5b7ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568338685604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390a15050505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101549050919050565b60008082600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff16151561213857600080fd5b61214184612c36565b915061214b612d59565b6064600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540281151561219757fe5b0492505050919050565b6003602052816000526040600020818154811015156121bc57fe5b9060005260206000209001600091509150508054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156122625780601f1061223757610100808354040283529160200191612262565b820191906000526020600020905b81548152906001019060200180831161224557829003601f168201915b505050505081565b600c54341015151561227b57600080fd5b80600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff1615156122d757600080fd5b61232c34600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101546135f690919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054141561249b57600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161244b919061362d565b9160005260206000209001600033909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505b61252d34600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546135f690919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507f66a9138482c99e9baf08860110ef332cc0c23b4a199a53593d8db0fc8f96fbfc338334604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a15050565b60046020528060005260406000206000915090505481565b60095481565b600f5481565b6000806000833373ffffffffffffffffffffffffffffffffffffffff16600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151561271957600080fd5b84600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff16151561277557600080fd5b6000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160146101000a81548160ff0219169083151502179055506127e6600160095461361490919063ffffffff16565b600981905550600094505b6008805490508510156128bb578573ffffffffffffffffffffffffffffffffffffffff1660088681548110151561282457fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156128ae5760088581548110151561287b57fe5b906000526020600020900160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556128bb565b84806001019550506127f1565b600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054935061299284600160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015461361490919063ffffffff16565b600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550612a7243600e546135f690919063ffffffff16565b9250612ad9846000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000868152602001908152602001600020546135f690919063ffffffff16565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000858152602001908152602001600020819055506000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018054806001018281612b829190613659565b9160005260206000209001600085909190915055507f4edf3e325d0063213a39f9085522994a1c44bea5f39e7d63ef61260a1e58c6d33387604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a1505050505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050919050565b600d5481565b600e5481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff169050919050565b600b5481565b6000600a54905090565b600080612d6e613685565b600080600033600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff161515612dcf57600080fd5b87600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff161515612e2b57600080fd5b612e3433612c36565b9750612e3f89612c36565b9650600560008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515612ed757600080fd5b6001600560008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600460008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550604b612fc4612d59565b6064600460008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540281151561301057fe5b041015156134e65760016008805490500360405180591061302e5750595b9080825280602002602001820160405250955060009450600093505b600880549050841015613357578673ffffffffffffffffffffffffffffffffffffffff166130b160088681548110151561308057fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16612c36565b73ffffffffffffffffffffffffffffffffffffffff16141561334a576130e3600160095461361490919063ffffffff16565b6009819055506008848154811015156130f857fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16868680600101975081518110151561313857fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060088481548110151561318357fe5b906000526020600020900160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600160006008868154811015156131c457fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000820160146101000a81549060ff021916905560018201600090555050600360008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006132bb91906136c1565b600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061330691906136e2565b600460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600090555b838060010194505061304a565b600092505b600780549050831015613439578673ffffffffffffffffffffffffffffffffffffffff1660078481548110151561338f57fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561342c576007838154811015156133e657fe5b906000526020600020900160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600a6000815480929190600190039190505550613439565b828060010193505061335c565b7fe18d61a5bf4aa2ab40afc88aa9039d27ae17ff4ec1c65f5f414df6f02ce8b35e8787604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019060200280838360005b838110156134d15780820151818401526020810190506134b6565b50505050905001935050505060405180910390a15b505050505050505050565b600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816135429190613703565b91600052602060002090016000848490919290919250919061356592919061372f565b50507f949360d814b28a3b393a68909efe1fee120ee09cac30f360a0f80ab5415a611a338383604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001806020018281038252848482818152602001925080828437820191505094505050505060405180910390a15050565b600c5481565b600080828401905083811015151561360a57fe5b8091505092915050565b600082821115151561362257fe5b818303905092915050565b8154818355818115116136545781836000526020600020918201910161365391906137af565b5b505050565b8154818355818115116136805781836000526020600020918201910161367f91906137af565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b50805460008255906000526020600020908101906136df91906137d4565b50565b508054600082559060005260206000209081019061370091906137af565b50565b81548183558181151161372a5781836000526020600020918201910161372991906137d4565b5b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061377057803560ff191683800117855561379e565b8280016001018555821561379e579182015b8281111561379d578235825591602001919060010190613782565b5b5090506137ab91906137af565b5090565b6137d191905b808211156137cd5760008160009055506001016137b5565b5090565b90565b6137fd91905b808211156137f957600081816137f09190613800565b506001016137da565b5090565b90565b50805460018160011615610100020316600290046000825580601f106138265750613845565b601f01602090049060005260206000209081019061384491906137af565b5b505600a165627a7a72305820f5bbb127b52ce86c873faef85cff176563476a5e49a3d88eaa9a06a8f432c9080029"); +} diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs b/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs new file mode 100644 index 00000000000..4dd7f74a7f2 --- /dev/null +++ b/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs @@ -0,0 +1,12 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Core; +using Nethermind.Int256; + +namespace Nethermind.Xdc; +internal interface IMasternodeVotingContract +{ + Address[] GetCandidates(BlockHeader blockHeader); + UInt256 GetCandidateStake(BlockHeader blockHeader, Address candidate); +} diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs new file mode 100644 index 00000000000..cbdd1230dc3 --- /dev/null +++ b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs @@ -0,0 +1,96 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Abi; +using Nethermind.Blockchain; +using Nethermind.Blockchain.Contracts; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Specs; +using Nethermind.Evm.State; +using Nethermind.Int256; +using Nethermind.State; +using System; + +namespace Nethermind.Xdc; +internal class MasternodeVotingContract : Contract, IMasternodeVotingContract +{ + private readonly IWorldState _worldState; + + private IConstantContract _constant; + + public MasternodeVotingContract( + IWorldState worldState, + IAbiEncoder abiEncoder, + Address contractAddress, + IReadOnlyTxProcessorSource readOnlyTxProcessorSource) + : base(abiEncoder, contractAddress ?? throw new ArgumentNullException(nameof(contractAddress)), new AbiDefinition()) + { + _constant = GetConstant(readOnlyTxProcessorSource); + _worldState = worldState; + } + + public UInt256 GetCandidateStake(BlockHeader blockHeader, Address candidate) + { + var callInfo = new CallInfo(blockHeader, "getCandidateCap", Address.SystemUser, candidate); + var result = this._constant.Call(callInfo); + if (result.Length != 1) + throw new InvalidOperationException("Expected 'getCandidateCap' to return exactly one result."); + + return (UInt256)result[0]!; + } + + public Address[] GetCandidates(BlockHeader blockHeader) + { + var callInfo = new CallInfo(blockHeader, "getCandidates", Address.SystemUser); + var result = this._constant.Call(callInfo); + return (Address[])result!; + } + + /// + /// Optimization to get candidates directly from storage without going through EVM call + /// + /// + /// + public Address[] GetCandidates(XdcBlockHeader header) + { + var variableSlot = CandidateContractSlots.Candidates; + Span input = [(byte)variableSlot]; + var slot = new UInt256(Keccak.Compute(input).Bytes); + using var state = _worldState.BeginScope(header); + ReadOnlySpan storageCell = _worldState.Get(new StorageCell(ContractAddress, slot)); + var length = new UInt256(storageCell); + Address[] candidates = new Address[(ulong)length]; + for (int i = 0; i < length; i++) + { + var key = CalculateArrayKey(slot, (ulong)i, 1); + candidates[i] = new Address(_worldState.Get(new StorageCell(ContractAddress, key))); + } + return candidates; + } + + private UInt256 CalculateArrayKey(UInt256 slot, ulong index, ulong size) + { + return slot + new UInt256(index * size); + } + + private enum CandidateContractSlots : byte + { + WithdrawsState, + ValidatorsState, + Voters, + KYCString, + InvalidKYCCount, + HasVotedInvalid, + OwnerToCandidate, + Owners, + Candidates, + CandidateCount, + OwnerCount, + MinCandidateCap, + MinVoterCap, + MaxValidatorNumber, + CandidateWithdrawDelay, + VoterWithdrawDelay + } +} diff --git a/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs b/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs index 7b207f6b208..09195bdf83f 100644 --- a/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs @@ -98,6 +98,7 @@ public interface IXdcReleaseSpec : IReleaseSpec public int MinimumSigningTx { get; set; } // Signing txs that a node needs to produce to get out of penalty, after `LimitPenaltyEpoch` public List V2Configs { get; set; } Address[] GenesisMasterNodes { get; set; } + Address MasternodeVotingContract { get; set; } public void ApplyV2Config(ulong round); } diff --git a/src/Nethermind/Nethermind.Xdc/State/MasternodeVotingContract.cs b/src/Nethermind/Nethermind.Xdc/State/MasternodeVotingContract.cs deleted file mode 100644 index 1bd19f7973e..00000000000 --- a/src/Nethermind/Nethermind.Xdc/State/MasternodeVotingContract.cs +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Blockchain.Contracts; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Nethermind.Xdc.State; -internal class MasternodeVotingContract : Contract -{ - -} diff --git a/src/Nethermind/Nethermind.Xdc/XdcContractStateReader.cs b/src/Nethermind/Nethermind.Xdc/XdcContractStateReader.cs deleted file mode 100644 index 524ea583a38..00000000000 --- a/src/Nethermind/Nethermind.Xdc/XdcContractStateReader.cs +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Microsoft.AspNetCore.Mvc; -using Nethermind.Core; -using Nethermind.Core.Crypto; -using Nethermind.Core.Specs; -using Nethermind.Evm.State; -using Nethermind.Int256; -using Nethermind.Serialization.Rlp; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Nethermind.Xdc; - -internal class XdcContractStateReader(IWorldState worldState, ISpecProvider specProvider) -{ - - public Address[] GetCandidates(XdcBlockHeader header) - { - var spec = specProvider.GetXdcSpec(header, header.ExtraConsensusData.BlockRound); - var variableSlot = CandidateContractSlots.Candidates; - Span input = [(byte)variableSlot]; - var slot = new UInt256(Keccak.Compute(input).Bytes); - using var state = worldState.BeginScope(header); - ReadOnlySpan storageCell = worldState.Get(new StorageCell(spec.MasternodeVotingContract, slot)); - var length = new UInt256(storageCell); - Address[] candidates = new Address[(ulong)length]; - for (int i = 0; i < length; i++) - { - var key = CalculateArrayKey(slot, (ulong)i, 1); - candidates[i] = new Address(worldState.Get(new StorageCell(spec.MasternodeVotingContract, key))); - } - return candidates; - } - - private UInt256 CalculateArrayKey(UInt256 slot, ulong index, ulong size) - { - return slot + new UInt256(index * size); - } - - public UInt256 GetCandidateStake(Address candidate) - { - var variableSlot = CandidateContractSlots.ValidatorsState; - - } - - private enum CandidateContractSlots : byte - { - WithdrawsState, - ValidatorsState, - Voters, - KYCString, - InvalidKYCCount, - HasVotedInvalid, - OwnerToCandidate, - Owners, - Candidates, - CandidateCount, - OwnerCount, - MinCandidateCap, - MinVoterCap, - MaxValidatorNumber, - CandidateWithdrawDelay, - VoterWithdrawDelay - } -} - - From 55190f7c19a5a7ad68ee840233fdd54e94bfc791 Mon Sep 17 00:00:00 2001 From: ak88 Date: Tue, 18 Nov 2025 17:32:15 +0100 Subject: [PATCH 04/25] fix --- src/Nethermind/Nethermind.Xdc/Contracts/ContractData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/ContractData.cs b/src/Nethermind/Nethermind.Xdc/Contracts/ContractData.cs index 0c08f0caeea..4eb1db5c1fa 100644 --- a/src/Nethermind/Nethermind.Xdc/Contracts/ContractData.cs +++ b/src/Nethermind/Nethermind.Xdc/Contracts/ContractData.cs @@ -12,7 +12,7 @@ namespace Nethermind.Xdc.Contracts; internal static class ContractData { // XDCValidatorABI is the input ABI used to generate the binding from. - public static string XDCValidatorABI() => "[{\"constant\":false,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"propose\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"owners\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"},{\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"unvote\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCandidates\",\"outputs\":[{\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"ownerCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"address\"}],\"name\":\"hasVotedInvalid\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_blockNumber\",\"type\":\"uint256\"}],\"name\":\"getWithdrawCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownerToCandidate\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"getVoters\",\"outputs\":[{\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getWithdrawBlockNumbers\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"},{\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"getVoterCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"getLatestKYC\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"candidates\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_blockNumber\",\"type\":\"uint256\"},{\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"getCandidateCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_invalidCandidate\",\"type\":\"address\"}],\"name\":\"invalidPercent\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"KYCString\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"vote\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"invalidKYCCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"candidateCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"voterWithdrawDelay\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"resign\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"getCandidateOwner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"getHashCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxValidatorNumber\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"candidateWithdrawDelay\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"isCandidate\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"minCandidateCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getOwnerCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_invalidCandidate\",\"type\":\"address\"}],\"name\":\"voteInvalidKYC\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"kychash\",\"type\":\"string\"}],\"name\":\"uploadKYC\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"minVoterCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_candidates\",\"type\":\"address[]\"},{\"name\":\"_caps\",\"type\":\"uint256[]\"},{\"name\":\"_firstOwner\",\"type\":\"address\"},{\"name\":\"_minCandidateCap\",\"type\":\"uint256\"},{\"name\":\"_minVoterCap\",\"type\":\"uint256\"},{\"name\":\"_maxValidatorNumber\",\"type\":\"uint256\"},{\"name\":\"_candidateWithdrawDelay\",\"type\":\"uint256\"},{\"name\":\"_voterWithdrawDelay\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_voter\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_candidate\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"Vote\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_voter\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_candidate\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"Unvote\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_candidate\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"Propose\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"Resign\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_blockNumber\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"kycHash\",\"type\":\"string\"}],\"name\":\"UploadedKYC\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_masternodeOwner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_masternodes\",\"type\":\"address[]\"}],\"name\":\"InvalidatedNode\",\"type\":\"event\"}]" + public static string XDCValidatorABI() => "[{\"constant\":false,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"propose\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"owners\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"},{\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"unvote\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCandidates\",\"outputs\":[{\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"ownerCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"address\"}],\"name\":\"hasVotedInvalid\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_blockNumber\",\"type\":\"uint256\"}],\"name\":\"getWithdrawCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownerToCandidate\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"getVoters\",\"outputs\":[{\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getWithdrawBlockNumbers\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"},{\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"getVoterCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"getLatestKYC\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"candidates\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_blockNumber\",\"type\":\"uint256\"},{\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"getCandidateCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_invalidCandidate\",\"type\":\"address\"}],\"name\":\"invalidPercent\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"KYCString\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"vote\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"invalidKYCCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"candidateCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"voterWithdrawDelay\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"resign\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"getCandidateOwner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"getHashCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxValidatorNumber\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"candidateWithdrawDelay\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"isCandidate\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"minCandidateCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getOwnerCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_invalidCandidate\",\"type\":\"address\"}],\"name\":\"voteInvalidKYC\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"kychash\",\"type\":\"string\"}],\"name\":\"uploadKYC\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"minVoterCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_candidates\",\"type\":\"address[]\"},{\"name\":\"_caps\",\"type\":\"uint256[]\"},{\"name\":\"_firstOwner\",\"type\":\"address\"},{\"name\":\"_minCandidateCap\",\"type\":\"uint256\"},{\"name\":\"_minVoterCap\",\"type\":\"uint256\"},{\"name\":\"_maxValidatorNumber\",\"type\":\"uint256\"},{\"name\":\"_candidateWithdrawDelay\",\"type\":\"uint256\"},{\"name\":\"_voterWithdrawDelay\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_voter\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_candidate\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"Vote\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_voter\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_candidate\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"Unvote\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_candidate\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"Propose\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"Resign\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_blockNumber\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"kycHash\",\"type\":\"string\"}],\"name\":\"UploadedKYC\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_masternodeOwner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_masternodes\",\"type\":\"address[]\"}],\"name\":\"InvalidatedNode\",\"type\":\"event\"}]"; // XDCValidatorBin is the compiled bytecode used for deploying new contracts. public static byte[] XDCValidatorBin() => Bytes.FromHexString("0x606060405260006009556000600a5534156200001a57600080fd5b60405162003dcc38038062003dcc83398101604052808051820191906020018051820191906020018051906020019091908051906020019091908051906020019091908051906020019091908051906020019091908051906020019091905050600085600b8190555084600c8190555083600d8190555082600e8190555081600f81905550885160098190555060078054806001018281620000bd9190620004f1565b9160005260206000209001600089909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600a60008154809291906001019190505550600090505b8851811015620004e25760088054806001018281620001439190620004f1565b916000526020600020900160008b848151811015156200015f57fe5b90602001906020020151909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506060604051908101604052808873ffffffffffffffffffffffffffffffffffffffff1681526020016001151581526020018983815181101515620001ea57fe5b90602001906020020151815250600160008b848151811015156200020a57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548160ff02191690831515021790555060408201518160010155905050600260008a83815181101515620002d557fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816200032d9190620004f1565b9160005260206000209001600089909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281620003cf9190620004f1565b916000526020600020900160008b84815181101515620003eb57fe5b90602001906020020151909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600b54600160008b848151811015156200044c57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550808060010191505062000123565b50505050505050505062000548565b8154818355818115116200051b578183600052602060002091820191016200051a919062000520565b5b505050565b6200054591905b808211156200054157600081600090555060010162000527565b5090565b90565b61387480620005586000396000f300606060405260043610610196576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063012679511461019b578063025e7c27146101c957806302aa9be21461022c57806306a49fce1461026e5780630db02622146102d85780630e3e4fb81461030157806315febd68146103715780632a3640b1146103a85780632d15cc041461042a5780632f9c4bba146104b8578063302b687214610522578063326586521461058e5780633477ee2e14610640578063441a3e70146106a357806358e7525f146106cf5780635b860d271461071c5780635b9cd8cc146107695780636dd7d8ea1461082457806372e44a3814610852578063a9a981a31461089f578063a9ff959e146108c8578063ae6e43f5146108f1578063b642facd1461092a578063c45607df146109a3578063d09f1ab4146109f0578063d161c76714610a19578063d51b9e9314610a42578063d55b7dff14610a93578063ef18374a14610abc578063f2ee3c7d14610ae5578063f5c9512514610b1e578063f8ac9dd514610b4c575b600080fd5b6101c7600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610b75565b005b34156101d457600080fd5b6101ea60048080359060200190919050506111fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561023757600080fd5b61026c600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061123b565b005b341561027957600080fd5b610281611796565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102c45780820151818401526020810190506102a9565b505050509050019250505060405180910390f35b34156102e357600080fd5b6102eb61182a565b6040518082815260200191505060405180910390f35b341561030c57600080fd5b610357600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611830565b604051808215151515815260200191505060405180910390f35b341561037c57600080fd5b610392600480803590602001909190505061185f565b6040518082815260200191505060405180910390f35b34156103b357600080fd5b6103e8600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506118bb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561043557600080fd5b610461600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611909565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156104a4578082015181840152602081019050610489565b505050509050019250505060405180910390f35b34156104c357600080fd5b6104cb6119dc565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561050e5780820151818401526020810190506104f3565b505050509050019250505060405180910390f35b341561052d57600080fd5b610578600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611a79565b6040518082815260200191505060405180910390f35b341561059957600080fd5b6105c5600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611b03565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156106055780820151818401526020810190506105ea565b50505050905090810190601f1680156106325780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561064b57600080fd5b6106616004808035906020019091905050611da2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156106ae57600080fd5b6106cd6004808035906020019091908035906020019091905050611de1565b005b34156106da57600080fd5b610706600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061208d565b6040518082815260200191505060405180910390f35b341561072757600080fd5b610753600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506120d9565b6040518082815260200191505060405180910390f35b341561077457600080fd5b6107a9600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506121a1565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156107e95780820151818401526020810190506107ce565b50505050905090810190601f1680156108165780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610850600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061226a565b005b341561085d57600080fd5b610889600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612653565b6040518082815260200191505060405180910390f35b34156108aa57600080fd5b6108b261266b565b6040518082815260200191505060405180910390f35b34156108d357600080fd5b6108db612671565b6040518082815260200191505060405180910390f35b34156108fc57600080fd5b610928600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612677565b005b341561093557600080fd5b610961600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612c36565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156109ae57600080fd5b6109da600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612ca2565b6040518082815260200191505060405180910390f35b34156109fb57600080fd5b610a03612cee565b6040518082815260200191505060405180910390f35b3415610a2457600080fd5b610a2c612cf4565b6040518082815260200191505060405180910390f35b3415610a4d57600080fd5b610a79600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612cfa565b604051808215151515815260200191505060405180910390f35b3415610a9e57600080fd5b610aa6612d53565b6040518082815260200191505060405180910390f35b3415610ac757600080fd5b610acf612d59565b6040518082815260200191505060405180910390f35b3415610af057600080fd5b610b1c600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612d63565b005b3415610b2957600080fd5b610b4a600480803590602001908201803590602001919091929050506134f1565b005b3415610b5757600080fd5b610b5f6135f0565b6040518082815260200191505060405180910390f35b6000600b543410151515610b8857600080fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050141580610c1c57506000600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050115b1515610c2757600080fd5b81600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff16151515610c8457600080fd5b610cd934600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101546135f690919063ffffffff16565b915060088054806001018281610cef919061362d565b9160005260206000209001600085909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506060604051908101604052803373ffffffffffffffffffffffffffffffffffffffff16815260200160011515815260200183815250600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548160ff02191690831515021790555060408201518160010155905050610eb834600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546135f690919063ffffffff16565b600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610f5160016009546135f690919063ffffffff16565b6009819055506000600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905014156110185760078054806001018281610fb6919061362d565b9160005260206000209001600033909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600a600081548092919060010191905055505b600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281611069919061362d565b9160005260206000209001600085909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281611109919061362d565b9160005260206000209001600033909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550507f7635f1d87b47fba9f2b09e56eb4be75cca030e0cb179c1602ac9261d39a8f5c1338434604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a1505050565b60078181548110151561120b57fe5b90600052602060002090016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000828280600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156112cd57600080fd5b3373ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561140657600b546113f882600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461361490919063ffffffff16565b1015151561140557600080fd5b5b61145b84600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015461361490919063ffffffff16565b600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018190555061153384600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461361490919063ffffffff16565b600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506115cb43600f546135f690919063ffffffff16565b9250611632846000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000868152602001908152602001600020546135f690919063ffffffff16565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000858152602001908152602001600020819055506000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010180548060010182816116db9190613659565b9160005260206000209001600085909190915055507faa0e554f781c3c3b2be110a0557f260f11af9a8aa2c64bc1e7a31dbb21e32fa2338686604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a15050505050565b61179e613685565b600880548060200260200160405190810160405280929190818152602001828054801561182057602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116117d6575b5050505050905090565b600a5481565b60056020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60008060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000838152602001908152602001600020549050919050565b6006602052816000526040600020818154811015156118d657fe5b90600052602060002090016000915091509054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611911613685565b600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156119d057602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311611986575b50505050509050919050565b6119e4613699565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101805480602002602001604051908101604052809291908181526020018280548015611a6f57602002820191906000526020600020905b815481526020019060010190808311611a5b575b5050505050905090565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b611b0b6136ad565b611b1482612cfa565b15611c655760036000611b2684612c36565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600160036000611b6f86612c36565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905003815481101515611bba57fe5b90600052602060002090018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611c595780601f10611c2e57610100808354040283529160200191611c59565b820191906000526020600020905b815481529060010190602001808311611c3c57829003601f168201915b50505050509050611d9d565b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905003815481101515611cf657fe5b90600052602060002090018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611d955780601f10611d6a57610100808354040283529160200191611d95565b820191906000526020600020905b815481529060010190602001808311611d7857829003601f168201915b505050505090505b919050565b600881815481101515611db157fe5b90600052602060002090016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008282600082111515611df457600080fd5b814310151515611e0357600080fd5b60008060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001600084815260200190815260200160002054111515611e6457600080fd5b816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010182815481101515611eb357fe5b906000526020600020900154141515611ecb57600080fd5b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008681526020019081526020016000205492506000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000868152602001908152602001600020600090556000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010184815481101515611fc457fe5b9060005260206000209001600090553373ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f19350505050151561201357600080fd5b7ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568338685604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390a15050505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101549050919050565b60008082600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff16151561213857600080fd5b61214184612c36565b915061214b612d59565b6064600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540281151561219757fe5b0492505050919050565b6003602052816000526040600020818154811015156121bc57fe5b9060005260206000209001600091509150508054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156122625780601f1061223757610100808354040283529160200191612262565b820191906000526020600020905b81548152906001019060200180831161224557829003601f168201915b505050505081565b600c54341015151561227b57600080fd5b80600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff1615156122d757600080fd5b61232c34600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101546135f690919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054141561249b57600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161244b919061362d565b9160005260206000209001600033909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505b61252d34600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546135f690919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507f66a9138482c99e9baf08860110ef332cc0c23b4a199a53593d8db0fc8f96fbfc338334604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a15050565b60046020528060005260406000206000915090505481565b60095481565b600f5481565b6000806000833373ffffffffffffffffffffffffffffffffffffffff16600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151561271957600080fd5b84600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff16151561277557600080fd5b6000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160146101000a81548160ff0219169083151502179055506127e6600160095461361490919063ffffffff16565b600981905550600094505b6008805490508510156128bb578573ffffffffffffffffffffffffffffffffffffffff1660088681548110151561282457fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156128ae5760088581548110151561287b57fe5b906000526020600020900160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556128bb565b84806001019550506127f1565b600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054935061299284600160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015461361490919063ffffffff16565b600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550612a7243600e546135f690919063ffffffff16565b9250612ad9846000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000868152602001908152602001600020546135f690919063ffffffff16565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000858152602001908152602001600020819055506000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018054806001018281612b829190613659565b9160005260206000209001600085909190915055507f4edf3e325d0063213a39f9085522994a1c44bea5f39e7d63ef61260a1e58c6d33387604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a1505050505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050919050565b600d5481565b600e5481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff169050919050565b600b5481565b6000600a54905090565b600080612d6e613685565b600080600033600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff161515612dcf57600080fd5b87600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff161515612e2b57600080fd5b612e3433612c36565b9750612e3f89612c36565b9650600560008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515612ed757600080fd5b6001600560008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600460008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550604b612fc4612d59565b6064600460008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540281151561301057fe5b041015156134e65760016008805490500360405180591061302e5750595b9080825280602002602001820160405250955060009450600093505b600880549050841015613357578673ffffffffffffffffffffffffffffffffffffffff166130b160088681548110151561308057fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16612c36565b73ffffffffffffffffffffffffffffffffffffffff16141561334a576130e3600160095461361490919063ffffffff16565b6009819055506008848154811015156130f857fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16868680600101975081518110151561313857fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060088481548110151561318357fe5b906000526020600020900160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600160006008868154811015156131c457fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000820160146101000a81549060ff021916905560018201600090555050600360008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006132bb91906136c1565b600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061330691906136e2565b600460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600090555b838060010194505061304a565b600092505b600780549050831015613439578673ffffffffffffffffffffffffffffffffffffffff1660078481548110151561338f57fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561342c576007838154811015156133e657fe5b906000526020600020900160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600a6000815480929190600190039190505550613439565b828060010193505061335c565b7fe18d61a5bf4aa2ab40afc88aa9039d27ae17ff4ec1c65f5f414df6f02ce8b35e8787604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019060200280838360005b838110156134d15780820151818401526020810190506134b6565b50505050905001935050505060405180910390a15b505050505050505050565b600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816135429190613703565b91600052602060002090016000848490919290919250919061356592919061372f565b50507f949360d814b28a3b393a68909efe1fee120ee09cac30f360a0f80ab5415a611a338383604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001806020018281038252848482818152602001925080828437820191505094505050505060405180910390a15050565b600c5481565b600080828401905083811015151561360a57fe5b8091505092915050565b600082821115151561362257fe5b818303905092915050565b8154818355818115116136545781836000526020600020918201910161365391906137af565b5b505050565b8154818355818115116136805781836000526020600020918201910161367f91906137af565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b50805460008255906000526020600020908101906136df91906137d4565b50565b508054600082559060005260206000209081019061370091906137af565b50565b81548183558181151161372a5781836000526020600020918201910161372991906137d4565b5b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061377057803560ff191683800117855561379e565b8280016001018555821561379e579182015b8281111561379d578235825591602001919060010190613782565b5b5090506137ab91906137af565b5090565b6137d191905b808211156137cd5760008160009055506001016137b5565b5090565b90565b6137fd91905b808211156137f957600081816137f09190613800565b506001016137da565b5090565b90565b50805460018160011615610100020316600290046000825580601f106138265750613845565b601f01602090049060005260206000209081019061384491906137af565b5b505600a165627a7a72305820f5bbb127b52ce86c873faef85cff176563476a5e49a3d88eaa9a06a8f432c9080029"); From 0f5adc33088b9f0b0d17b4d2025493e0603f6da6 Mon Sep 17 00:00:00 2001 From: ak88 Date: Wed, 19 Nov 2025 12:52:27 +0100 Subject: [PATCH 05/25] abi json --- .../Contracts/AbiLoadTests.cs | 22 + .../Contracts/XdcContractTests.cs | 77 +++ .../Contracts/MasternodeVotingContract.cs | 9 +- .../Contracts/MasternodeVotingContract.json | 549 ++++++++++++++++++ .../{ContractData.cs => XdcContractData.cs} | 5 +- .../Nethermind.Xdc/Nethermind.Xdc.csproj | 8 + 6 files changed, 665 insertions(+), 5 deletions(-) create mode 100644 src/Nethermind/Nethermind.Xdc.Test/Contracts/AbiLoadTests.cs create mode 100644 src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcContractTests.cs create mode 100644 src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.json rename src/Nethermind/Nethermind.Xdc/Contracts/{ContractData.cs => XdcContractData.cs} (77%) diff --git a/src/Nethermind/Nethermind.Xdc.Test/Contracts/AbiLoadTests.cs b/src/Nethermind/Nethermind.Xdc.Test/Contracts/AbiLoadTests.cs new file mode 100644 index 00000000000..01b18e3dca5 --- /dev/null +++ b/src/Nethermind/Nethermind.Xdc.Test/Contracts/AbiLoadTests.cs @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using FluentAssertions; +using Nethermind.Blockchain.Contracts.Json; +using Newtonsoft.Json.Linq; +using NUnit.Framework; +using System; + +namespace Nethermind.Xdc.Test.Contracts; +internal class AbiLoadTests +{ + [TestCase(typeof(MasternodeVotingContract))] + public void Can_load_contract(Type contractType) + { + var parser = new AbiDefinitionParser(); + var json = AbiDefinitionParser.LoadContract(contractType); + var contract = parser.Parse(json); + var serialized = AbiDefinitionParser.Serialize(contract); + JToken.Parse(serialized).Should().ContainSubtree(json); + } +} diff --git a/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcContractTests.cs b/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcContractTests.cs new file mode 100644 index 00000000000..bea56a4fd28 --- /dev/null +++ b/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcContractTests.cs @@ -0,0 +1,77 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Autofac; +using Nethermind.Abi; +using Nethermind.Blockchain; +using Nethermind.Consensus.Processing; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; +using Nethermind.Core.Specs; +using Nethermind.Core.Test; +using Nethermind.Core.Test.Builders; +using Nethermind.Crypto; +using Nethermind.Evm; +using Nethermind.Evm.State; +using Nethermind.Evm.Tracing; +using Nethermind.Evm.TransactionProcessing; +using Nethermind.Logging; +using Nethermind.Specs; +using Nethermind.Specs.Forks; +using Nethermind.State; +using Nethermind.Xdc.Contracts; +using NSubstitute; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static Nethermind.Consensus.Processing.AutoReadOnlyTxProcessingEnvFactory; + +namespace Nethermind.Xdc.Test; +internal class XdcContractTests +{ + private ISpecProvider _specProvider; + private IEthereumEcdsa _ethereumEcdsa; + private ITransactionProcessor _transactionProcessor; + private IWorldState _stateProvider; + + [SetUp] + public void Setup() + { + _specProvider = new TestSpecProvider(Shanghai.Instance); + _stateProvider = TestWorldStateFactory.CreateForTest(); + EthereumCodeInfoRepository codeInfoRepository = new(_stateProvider); + VirtualMachine virtualMachine = new(new TestBlockhashProvider(_specProvider), _specProvider, LimboLogs.Instance); + _transactionProcessor = new TransactionProcessor(BlobBaseFeeCalculator.Instance, _specProvider, _stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); + _ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId); + } + + [Test] + public void MasternodeVotingContract() + { + PrivateKey sender = TestItem.PrivateKeyA; + PrivateKey signer = TestItem.PrivateKeyB; + Address codeSource = TestItem.AddressC; + var scope = _stateProvider.BeginScope(IWorldState.PreGenesis); + _stateProvider.CreateAccount(sender.Address, 1.Ether()); + //Save caller in storage slot 0 + byte[] code = XdcContractData.XDCValidatorBin(); + + DeployCode(codeSource, code); + scope.Dispose(); + + var masterVoting = new MasternodeVotingContract(_stateProvider, new AbiEncoder(), codeSource, new AutoReadOnlyTxProcessingEnv(_transactionProcessor, _stateProvider, Substitute.For())); + + var header = Build.A.BlockHeader.TestObject; + var candidates = masterVoting.GetCandidates(header); + } + + private void DeployCode(Address codeSource, byte[] code) + { + _stateProvider.CreateAccountIfNotExists(codeSource, 0); + _stateProvider.InsertCode(codeSource, ValueKeccak.Compute(code), code, Shanghai.Instance); + } +} diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs index cbdd1230dc3..0cb439951e0 100644 --- a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs +++ b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs @@ -24,12 +24,19 @@ public MasternodeVotingContract( IAbiEncoder abiEncoder, Address contractAddress, IReadOnlyTxProcessorSource readOnlyTxProcessorSource) - : base(abiEncoder, contractAddress ?? throw new ArgumentNullException(nameof(contractAddress)), new AbiDefinition()) + : base(abiEncoder, contractAddress ?? throw new ArgumentNullException(nameof(contractAddress)), CreateAbiDefinition()) { _constant = GetConstant(readOnlyTxProcessorSource); _worldState = worldState; } + private static AbiDefinition CreateAbiDefinition() + { + var abiDefinition = new AbiDefinition(); + + return abiDefinition; + } + public UInt256 GetCandidateStake(BlockHeader blockHeader, Address candidate) { var callInfo = new CallInfo(blockHeader, "getCandidateCap", Address.SystemUser, candidate); diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.json b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.json new file mode 100644 index 00000000000..828f4975ab8 --- /dev/null +++ b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.json @@ -0,0 +1,549 @@ +[ + { + "constant": false, + "inputs": [ + { + "name": "_candidate", + "type": "address" + } + ], + "name": "propose", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "owners", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_candidate", + "type": "address" + }, + { + "name": "_cap", + "type": "uint256" + } + ], + "name": "unvote", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCandidates", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "ownerCount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "address" + } + ], + "name": "hasVotedInvalid", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_blockNumber", + "type": "uint256" + } + ], + "name": "getWithdrawCap", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "uint256" + } + ], + "name": "ownerToCandidate", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_candidate", + "type": "address" + } + ], + "name": "getVoters", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getWithdrawBlockNumbers", + "outputs": [ + { + "name": "", + "type": "uint256[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_candidate", + "type": "address" + }, + { + "name": "_voter", + "type": "address" + } + ], + "name": "getVoterCap", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_address", + "type": "address" + } + ], + "name": "getLatestKYC", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "candidates", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_blockNumber", + "type": "uint256" + }, + { + "name": "_index", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_candidate", + "type": "address" + } + ], + "name": "getCandidateCap", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_invalidCandidate", + "type": "address" + } + ], + "name": "invalidPercent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "uint256" + } + ], + "name": "KYCString", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_candidate", + "type": "address" + } + ], + "name": "vote", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "invalidKYCCount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "candidateCount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "voterWithdrawDelay", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_candidate", + "type": "address" + } + ], + "name": "resign", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_candidate", + "type": "address" + } + ], + "name": "getCandidateOwner", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_address", + "type": "address" + } + ], + "name": "getHashCount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "maxValidatorNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "candidateWithdrawDelay", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_candidate", + "type": "address" + } + ], + "name": "isCandidate", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "minCandidateCap", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getOwnerCount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_invalidCandidate", + "type": "address" + } + ], + "name": "voteInvalidKYC", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "kychash", + "type": "string" + } + ], + "name": "uploadKYC", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "minVoterCap", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/ContractData.cs b/src/Nethermind/Nethermind.Xdc/Contracts/XdcContractData.cs similarity index 77% rename from src/Nethermind/Nethermind.Xdc/Contracts/ContractData.cs rename to src/Nethermind/Nethermind.Xdc/Contracts/XdcContractData.cs index 4eb1db5c1fa..7b7bed0f984 100644 --- a/src/Nethermind/Nethermind.Xdc/Contracts/ContractData.cs +++ b/src/Nethermind/Nethermind.Xdc/Contracts/XdcContractData.cs @@ -9,11 +9,8 @@ using System.Threading.Tasks; namespace Nethermind.Xdc.Contracts; -internal static class ContractData +internal static class XdcContractData { - // XDCValidatorABI is the input ABI used to generate the binding from. - public static string XDCValidatorABI() => "[{\"constant\":false,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"propose\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"owners\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"},{\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"unvote\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCandidates\",\"outputs\":[{\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"ownerCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"address\"}],\"name\":\"hasVotedInvalid\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_blockNumber\",\"type\":\"uint256\"}],\"name\":\"getWithdrawCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"ownerToCandidate\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"getVoters\",\"outputs\":[{\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getWithdrawBlockNumbers\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"},{\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"getVoterCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"getLatestKYC\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"candidates\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_blockNumber\",\"type\":\"uint256\"},{\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"getCandidateCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_invalidCandidate\",\"type\":\"address\"}],\"name\":\"invalidPercent\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"KYCString\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"vote\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"invalidKYCCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"candidateCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"voterWithdrawDelay\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"resign\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"getCandidateOwner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"getHashCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxValidatorNumber\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"candidateWithdrawDelay\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"isCandidate\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"minCandidateCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getOwnerCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_invalidCandidate\",\"type\":\"address\"}],\"name\":\"voteInvalidKYC\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"kychash\",\"type\":\"string\"}],\"name\":\"uploadKYC\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"minVoterCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_candidates\",\"type\":\"address[]\"},{\"name\":\"_caps\",\"type\":\"uint256[]\"},{\"name\":\"_firstOwner\",\"type\":\"address\"},{\"name\":\"_minCandidateCap\",\"type\":\"uint256\"},{\"name\":\"_minVoterCap\",\"type\":\"uint256\"},{\"name\":\"_maxValidatorNumber\",\"type\":\"uint256\"},{\"name\":\"_candidateWithdrawDelay\",\"type\":\"uint256\"},{\"name\":\"_voterWithdrawDelay\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_voter\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_candidate\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"Vote\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_voter\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_candidate\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"Unvote\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_candidate\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"Propose\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"Resign\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_blockNumber\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"kycHash\",\"type\":\"string\"}],\"name\":\"UploadedKYC\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_masternodeOwner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_masternodes\",\"type\":\"address[]\"}],\"name\":\"InvalidatedNode\",\"type\":\"event\"}]"; - // XDCValidatorBin is the compiled bytecode used for deploying new contracts. public static byte[] XDCValidatorBin() => Bytes.FromHexString("0x606060405260006009556000600a5534156200001a57600080fd5b60405162003dcc38038062003dcc83398101604052808051820191906020018051820191906020018051906020019091908051906020019091908051906020019091908051906020019091908051906020019091908051906020019091905050600085600b8190555084600c8190555083600d8190555082600e8190555081600f81905550885160098190555060078054806001018281620000bd9190620004f1565b9160005260206000209001600089909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600a60008154809291906001019190505550600090505b8851811015620004e25760088054806001018281620001439190620004f1565b916000526020600020900160008b848151811015156200015f57fe5b90602001906020020151909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506060604051908101604052808873ffffffffffffffffffffffffffffffffffffffff1681526020016001151581526020018983815181101515620001ea57fe5b90602001906020020151815250600160008b848151811015156200020a57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548160ff02191690831515021790555060408201518160010155905050600260008a83815181101515620002d557fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816200032d9190620004f1565b9160005260206000209001600089909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281620003cf9190620004f1565b916000526020600020900160008b84815181101515620003eb57fe5b90602001906020020151909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600b54600160008b848151811015156200044c57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550808060010191505062000123565b50505050505050505062000548565b8154818355818115116200051b578183600052602060002091820191016200051a919062000520565b5b505050565b6200054591905b808211156200054157600081600090555060010162000527565b5090565b90565b61387480620005586000396000f300606060405260043610610196576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063012679511461019b578063025e7c27146101c957806302aa9be21461022c57806306a49fce1461026e5780630db02622146102d85780630e3e4fb81461030157806315febd68146103715780632a3640b1146103a85780632d15cc041461042a5780632f9c4bba146104b8578063302b687214610522578063326586521461058e5780633477ee2e14610640578063441a3e70146106a357806358e7525f146106cf5780635b860d271461071c5780635b9cd8cc146107695780636dd7d8ea1461082457806372e44a3814610852578063a9a981a31461089f578063a9ff959e146108c8578063ae6e43f5146108f1578063b642facd1461092a578063c45607df146109a3578063d09f1ab4146109f0578063d161c76714610a19578063d51b9e9314610a42578063d55b7dff14610a93578063ef18374a14610abc578063f2ee3c7d14610ae5578063f5c9512514610b1e578063f8ac9dd514610b4c575b600080fd5b6101c7600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610b75565b005b34156101d457600080fd5b6101ea60048080359060200190919050506111fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561023757600080fd5b61026c600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061123b565b005b341561027957600080fd5b610281611796565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102c45780820151818401526020810190506102a9565b505050509050019250505060405180910390f35b34156102e357600080fd5b6102eb61182a565b6040518082815260200191505060405180910390f35b341561030c57600080fd5b610357600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611830565b604051808215151515815260200191505060405180910390f35b341561037c57600080fd5b610392600480803590602001909190505061185f565b6040518082815260200191505060405180910390f35b34156103b357600080fd5b6103e8600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506118bb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561043557600080fd5b610461600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611909565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156104a4578082015181840152602081019050610489565b505050509050019250505060405180910390f35b34156104c357600080fd5b6104cb6119dc565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561050e5780820151818401526020810190506104f3565b505050509050019250505060405180910390f35b341561052d57600080fd5b610578600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611a79565b6040518082815260200191505060405180910390f35b341561059957600080fd5b6105c5600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611b03565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156106055780820151818401526020810190506105ea565b50505050905090810190601f1680156106325780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561064b57600080fd5b6106616004808035906020019091905050611da2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156106ae57600080fd5b6106cd6004808035906020019091908035906020019091905050611de1565b005b34156106da57600080fd5b610706600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061208d565b6040518082815260200191505060405180910390f35b341561072757600080fd5b610753600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506120d9565b6040518082815260200191505060405180910390f35b341561077457600080fd5b6107a9600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506121a1565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156107e95780820151818401526020810190506107ce565b50505050905090810190601f1680156108165780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610850600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061226a565b005b341561085d57600080fd5b610889600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612653565b6040518082815260200191505060405180910390f35b34156108aa57600080fd5b6108b261266b565b6040518082815260200191505060405180910390f35b34156108d357600080fd5b6108db612671565b6040518082815260200191505060405180910390f35b34156108fc57600080fd5b610928600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612677565b005b341561093557600080fd5b610961600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612c36565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156109ae57600080fd5b6109da600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612ca2565b6040518082815260200191505060405180910390f35b34156109fb57600080fd5b610a03612cee565b6040518082815260200191505060405180910390f35b3415610a2457600080fd5b610a2c612cf4565b6040518082815260200191505060405180910390f35b3415610a4d57600080fd5b610a79600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612cfa565b604051808215151515815260200191505060405180910390f35b3415610a9e57600080fd5b610aa6612d53565b6040518082815260200191505060405180910390f35b3415610ac757600080fd5b610acf612d59565b6040518082815260200191505060405180910390f35b3415610af057600080fd5b610b1c600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612d63565b005b3415610b2957600080fd5b610b4a600480803590602001908201803590602001919091929050506134f1565b005b3415610b5757600080fd5b610b5f6135f0565b6040518082815260200191505060405180910390f35b6000600b543410151515610b8857600080fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050141580610c1c57506000600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050115b1515610c2757600080fd5b81600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff16151515610c8457600080fd5b610cd934600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101546135f690919063ffffffff16565b915060088054806001018281610cef919061362d565b9160005260206000209001600085909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506060604051908101604052803373ffffffffffffffffffffffffffffffffffffffff16815260200160011515815260200183815250600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548160ff02191690831515021790555060408201518160010155905050610eb834600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546135f690919063ffffffff16565b600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610f5160016009546135f690919063ffffffff16565b6009819055506000600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905014156110185760078054806001018281610fb6919061362d565b9160005260206000209001600033909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600a600081548092919060010191905055505b600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281611069919061362d565b9160005260206000209001600085909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281611109919061362d565b9160005260206000209001600033909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550507f7635f1d87b47fba9f2b09e56eb4be75cca030e0cb179c1602ac9261d39a8f5c1338434604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a1505050565b60078181548110151561120b57fe5b90600052602060002090016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000828280600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156112cd57600080fd5b3373ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561140657600b546113f882600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461361490919063ffffffff16565b1015151561140557600080fd5b5b61145b84600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015461361490919063ffffffff16565b600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018190555061153384600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461361490919063ffffffff16565b600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506115cb43600f546135f690919063ffffffff16565b9250611632846000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000868152602001908152602001600020546135f690919063ffffffff16565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000858152602001908152602001600020819055506000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010180548060010182816116db9190613659565b9160005260206000209001600085909190915055507faa0e554f781c3c3b2be110a0557f260f11af9a8aa2c64bc1e7a31dbb21e32fa2338686604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a15050505050565b61179e613685565b600880548060200260200160405190810160405280929190818152602001828054801561182057602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116117d6575b5050505050905090565b600a5481565b60056020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60008060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000838152602001908152602001600020549050919050565b6006602052816000526040600020818154811015156118d657fe5b90600052602060002090016000915091509054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611911613685565b600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156119d057602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311611986575b50505050509050919050565b6119e4613699565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101805480602002602001604051908101604052809291908181526020018280548015611a6f57602002820191906000526020600020905b815481526020019060010190808311611a5b575b5050505050905090565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b611b0b6136ad565b611b1482612cfa565b15611c655760036000611b2684612c36565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600160036000611b6f86612c36565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905003815481101515611bba57fe5b90600052602060002090018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611c595780601f10611c2e57610100808354040283529160200191611c59565b820191906000526020600020905b815481529060010190602001808311611c3c57829003601f168201915b50505050509050611d9d565b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905003815481101515611cf657fe5b90600052602060002090018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611d955780601f10611d6a57610100808354040283529160200191611d95565b820191906000526020600020905b815481529060010190602001808311611d7857829003601f168201915b505050505090505b919050565b600881815481101515611db157fe5b90600052602060002090016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008282600082111515611df457600080fd5b814310151515611e0357600080fd5b60008060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001600084815260200190815260200160002054111515611e6457600080fd5b816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010182815481101515611eb357fe5b906000526020600020900154141515611ecb57600080fd5b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008681526020019081526020016000205492506000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000868152602001908152602001600020600090556000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010184815481101515611fc457fe5b9060005260206000209001600090553373ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f19350505050151561201357600080fd5b7ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568338685604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390a15050505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101549050919050565b60008082600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff16151561213857600080fd5b61214184612c36565b915061214b612d59565b6064600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540281151561219757fe5b0492505050919050565b6003602052816000526040600020818154811015156121bc57fe5b9060005260206000209001600091509150508054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156122625780601f1061223757610100808354040283529160200191612262565b820191906000526020600020905b81548152906001019060200180831161224557829003601f168201915b505050505081565b600c54341015151561227b57600080fd5b80600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff1615156122d757600080fd5b61232c34600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101546135f690919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054141561249b57600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161244b919061362d565b9160005260206000209001600033909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505b61252d34600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546135f690919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507f66a9138482c99e9baf08860110ef332cc0c23b4a199a53593d8db0fc8f96fbfc338334604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a15050565b60046020528060005260406000206000915090505481565b60095481565b600f5481565b6000806000833373ffffffffffffffffffffffffffffffffffffffff16600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151561271957600080fd5b84600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff16151561277557600080fd5b6000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160146101000a81548160ff0219169083151502179055506127e6600160095461361490919063ffffffff16565b600981905550600094505b6008805490508510156128bb578573ffffffffffffffffffffffffffffffffffffffff1660088681548110151561282457fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156128ae5760088581548110151561287b57fe5b906000526020600020900160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556128bb565b84806001019550506127f1565b600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054935061299284600160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015461361490919063ffffffff16565b600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550612a7243600e546135f690919063ffffffff16565b9250612ad9846000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000868152602001908152602001600020546135f690919063ffffffff16565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000858152602001908152602001600020819055506000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018054806001018281612b829190613659565b9160005260206000209001600085909190915055507f4edf3e325d0063213a39f9085522994a1c44bea5f39e7d63ef61260a1e58c6d33387604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a1505050505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050919050565b600d5481565b600e5481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff169050919050565b600b5481565b6000600a54905090565b600080612d6e613685565b600080600033600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff161515612dcf57600080fd5b87600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff161515612e2b57600080fd5b612e3433612c36565b9750612e3f89612c36565b9650600560008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515612ed757600080fd5b6001600560008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600460008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550604b612fc4612d59565b6064600460008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540281151561301057fe5b041015156134e65760016008805490500360405180591061302e5750595b9080825280602002602001820160405250955060009450600093505b600880549050841015613357578673ffffffffffffffffffffffffffffffffffffffff166130b160088681548110151561308057fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16612c36565b73ffffffffffffffffffffffffffffffffffffffff16141561334a576130e3600160095461361490919063ffffffff16565b6009819055506008848154811015156130f857fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16868680600101975081518110151561313857fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060088481548110151561318357fe5b906000526020600020900160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600160006008868154811015156131c457fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000820160146101000a81549060ff021916905560018201600090555050600360008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006132bb91906136c1565b600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061330691906136e2565b600460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600090555b838060010194505061304a565b600092505b600780549050831015613439578673ffffffffffffffffffffffffffffffffffffffff1660078481548110151561338f57fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561342c576007838154811015156133e657fe5b906000526020600020900160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600a6000815480929190600190039190505550613439565b828060010193505061335c565b7fe18d61a5bf4aa2ab40afc88aa9039d27ae17ff4ec1c65f5f414df6f02ce8b35e8787604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019060200280838360005b838110156134d15780820151818401526020810190506134b6565b50505050905001935050505060405180910390a15b505050505050505050565b600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816135429190613703565b91600052602060002090016000848490919290919250919061356592919061372f565b50507f949360d814b28a3b393a68909efe1fee120ee09cac30f360a0f80ab5415a611a338383604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001806020018281038252848482818152602001925080828437820191505094505050505060405180910390a15050565b600c5481565b600080828401905083811015151561360a57fe5b8091505092915050565b600082821115151561362257fe5b818303905092915050565b8154818355818115116136545781836000526020600020918201910161365391906137af565b5b505050565b8154818355818115116136805781836000526020600020918201910161367f91906137af565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b50805460008255906000526020600020908101906136df91906137d4565b50565b508054600082559060005260206000209081019061370091906137af565b50565b81548183558181151161372a5781836000526020600020918201910161372991906137d4565b5b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061377057803560ff191683800117855561379e565b8280016001018555821561379e579182015b8281111561379d578235825591602001919060010190613782565b5b5090506137ab91906137af565b5090565b6137d191905b808211156137cd5760008160009055506001016137b5565b5090565b90565b6137fd91905b808211156137f957600081816137f09190613800565b506001016137da565b5090565b90565b50805460018160011615610100020316600290046000825580601f106138265750613845565b601f01602090049060005260206000209081019061384491906137af565b5b505600a165627a7a72305820f5bbb127b52ce86c873faef85cff176563476a5e49a3d88eaa9a06a8f432c9080029"); } diff --git a/src/Nethermind/Nethermind.Xdc/Nethermind.Xdc.csproj b/src/Nethermind/Nethermind.Xdc/Nethermind.Xdc.csproj index 0e18540fbbd..7f576e9d23f 100644 --- a/src/Nethermind/Nethermind.Xdc/Nethermind.Xdc.csproj +++ b/src/Nethermind/Nethermind.Xdc/Nethermind.Xdc.csproj @@ -4,6 +4,14 @@ annotations + + + + + + + + From 65943341b5d328eb990cc163ad0c7771982512c9 Mon Sep 17 00:00:00 2001 From: ak88 Date: Wed, 19 Nov 2025 13:34:41 +0100 Subject: [PATCH 06/25] working load test --- .../Contracts/{AbiLoadTests.cs => XdcAbiLoadTests.cs} | 5 +++-- .../Nethermind.Xdc.Test/Nethermind.Xdc.Test.csproj | 4 ++++ .../Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs | 2 +- .../Nethermind.Xdc/Contracts/MasternodeVotingContract.cs | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) rename src/Nethermind/Nethermind.Xdc.Test/Contracts/{AbiLoadTests.cs => XdcAbiLoadTests.cs} (87%) diff --git a/src/Nethermind/Nethermind.Xdc.Test/Contracts/AbiLoadTests.cs b/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcAbiLoadTests.cs similarity index 87% rename from src/Nethermind/Nethermind.Xdc.Test/Contracts/AbiLoadTests.cs rename to src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcAbiLoadTests.cs index 01b18e3dca5..a8e7398e45c 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/Contracts/AbiLoadTests.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcAbiLoadTests.cs @@ -1,14 +1,15 @@ // SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using FluentAssertions; +using FluentAssertions.Json; using Nethermind.Blockchain.Contracts.Json; +using Nethermind.Xdc.Contracts; using Newtonsoft.Json.Linq; using NUnit.Framework; using System; namespace Nethermind.Xdc.Test.Contracts; -internal class AbiLoadTests +internal class XdcAbiLoadTests { [TestCase(typeof(MasternodeVotingContract))] public void Can_load_contract(Type contractType) diff --git a/src/Nethermind/Nethermind.Xdc.Test/Nethermind.Xdc.Test.csproj b/src/Nethermind/Nethermind.Xdc.Test/Nethermind.Xdc.Test.csproj index 1843068955b..fd395e63a1b 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/Nethermind.Xdc.Test.csproj +++ b/src/Nethermind/Nethermind.Xdc.Test/Nethermind.Xdc.Test.csproj @@ -7,6 +7,10 @@ $(NoWarn);NUnit1032 + + + + diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs b/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs index 4dd7f74a7f2..8daadf8cb6e 100644 --- a/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs +++ b/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs @@ -4,7 +4,7 @@ using Nethermind.Core; using Nethermind.Int256; -namespace Nethermind.Xdc; +namespace Nethermind.Xdc.Contracts; internal interface IMasternodeVotingContract { Address[] GetCandidates(BlockHeader blockHeader); diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs index 0cb439951e0..91b8919e05c 100644 --- a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs +++ b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs @@ -12,7 +12,7 @@ using Nethermind.State; using System; -namespace Nethermind.Xdc; +namespace Nethermind.Xdc.Contracts; internal class MasternodeVotingContract : Contract, IMasternodeVotingContract { private readonly IWorldState _worldState; From aab09083f2f91a291e0d1b8b5bc977bd3695fd22 Mon Sep 17 00:00:00 2001 From: ak88 Date: Wed, 19 Nov 2025 16:14:24 +0100 Subject: [PATCH 07/25] test --- .../Contracts/XdcContractTests.cs | 36 +++++++++---------- .../Contracts/MasternodeVotingContract.cs | 6 ++-- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcContractTests.cs b/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcContractTests.cs index bea56a4fd28..49dbbbc1b4d 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcContractTests.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcContractTests.cs @@ -11,6 +11,7 @@ using Nethermind.Core.Specs; using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; +using Nethermind.Core.Test.Db; using Nethermind.Crypto; using Nethermind.Evm; using Nethermind.Evm.State; @@ -34,19 +35,21 @@ namespace Nethermind.Xdc.Test; internal class XdcContractTests { private ISpecProvider _specProvider; - private IEthereumEcdsa _ethereumEcdsa; private ITransactionProcessor _transactionProcessor; - private IWorldState _stateProvider; + private IWorldState _worldStateForContract; + private IWorldState _worldState; [SetUp] - public void Setup() + public async Task Setup() { + var dbProvider = await TestMemDbProvider.InitAsync(); + _specProvider = new TestSpecProvider(Shanghai.Instance); - _stateProvider = TestWorldStateFactory.CreateForTest(); - EthereumCodeInfoRepository codeInfoRepository = new(_stateProvider); + _worldState = TestWorldStateFactory.CreateWorldStateManagerForTest(dbProvider, NullLogManager.Instance).GlobalWorldState; + _worldStateForContract = TestWorldStateFactory.CreateWorldStateManagerForTest(dbProvider, NullLogManager.Instance).GlobalWorldState; + EthereumCodeInfoRepository codeInfoRepository = new(_worldState); VirtualMachine virtualMachine = new(new TestBlockhashProvider(_specProvider), _specProvider, LimboLogs.Instance); - _transactionProcessor = new TransactionProcessor(BlobBaseFeeCalculator.Instance, _specProvider, _stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); - _ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId); + _transactionProcessor = new TransactionProcessor(BlobBaseFeeCalculator.Instance, _specProvider, _worldState, virtualMachine, codeInfoRepository, LimboLogs.Instance); } [Test] @@ -55,23 +58,18 @@ public void MasternodeVotingContract() PrivateKey sender = TestItem.PrivateKeyA; PrivateKey signer = TestItem.PrivateKeyB; Address codeSource = TestItem.AddressC; - var scope = _stateProvider.BeginScope(IWorldState.PreGenesis); - _stateProvider.CreateAccount(sender.Address, 1.Ether()); //Save caller in storage slot 0 - byte[] code = XdcContractData.XDCValidatorBin(); - DeployCode(codeSource, code); - scope.Dispose(); + var masterVoting = new MasternodeVotingContract(_worldState, new AbiEncoder(), codeSource, new AutoReadOnlyTxProcessingEnv(_transactionProcessor, _worldState, Substitute.For())); - var masterVoting = new MasternodeVotingContract(_stateProvider, new AbiEncoder(), codeSource, new AutoReadOnlyTxProcessingEnv(_transactionProcessor, _stateProvider, Substitute.For())); + var scope = _worldState.BeginScope(IWorldState.PreGenesis); + _worldState.CreateAccount(sender.Address, 1.Ether()); + byte[] code = XdcContractData.XDCValidatorBin(); + _worldState.CreateAccountIfNotExists(codeSource, 0); + _worldState.InsertCode(codeSource, ValueKeccak.Compute(code), code, Shanghai.Instance); + _worldState.Commit (Shanghai.Instance, true); var header = Build.A.BlockHeader.TestObject; var candidates = masterVoting.GetCandidates(header); } - - private void DeployCode(Address codeSource, byte[] code) - { - _stateProvider.CreateAccountIfNotExists(codeSource, 0); - _stateProvider.InsertCode(codeSource, ValueKeccak.Compute(code), code, Shanghai.Instance); - } } diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs index 91b8919e05c..f738a06c9dd 100644 --- a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs +++ b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs @@ -4,6 +4,7 @@ using Nethermind.Abi; using Nethermind.Blockchain; using Nethermind.Blockchain.Contracts; +using Nethermind.Blockchain.Contracts.Json; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; @@ -32,9 +33,8 @@ public MasternodeVotingContract( private static AbiDefinition CreateAbiDefinition() { - var abiDefinition = new AbiDefinition(); - - return abiDefinition; + var abiDefinitionParser = new AbiDefinitionParser(); + return abiDefinitionParser.Parse(typeof(MasternodeVotingContract)); } public UInt256 GetCandidateStake(BlockHeader blockHeader, Address candidate) From e321be37f6f256b0e25cbe341312e56f4004cb53 Mon Sep 17 00:00:00 2001 From: ak88 Date: Thu, 20 Nov 2025 12:06:04 +0100 Subject: [PATCH 08/25] test --- .../Contracts/XdcContractTests.cs | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcContractTests.cs b/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcContractTests.cs index 49dbbbc1b4d..daf26e13b76 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcContractTests.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcContractTests.cs @@ -13,11 +13,13 @@ using Nethermind.Core.Test.Builders; using Nethermind.Core.Test.Db; using Nethermind.Crypto; +using Nethermind.Db; using Nethermind.Evm; using Nethermind.Evm.State; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Logging; +using Nethermind.Network; using Nethermind.Specs; using Nethermind.Specs.Forks; using Nethermind.State; @@ -34,40 +36,38 @@ namespace Nethermind.Xdc.Test; internal class XdcContractTests { - private ISpecProvider _specProvider; - private ITransactionProcessor _transactionProcessor; - private IWorldState _worldStateForContract; - private IWorldState _worldState; - - [SetUp] - public async Task Setup() - { - var dbProvider = await TestMemDbProvider.InitAsync(); - - _specProvider = new TestSpecProvider(Shanghai.Instance); - _worldState = TestWorldStateFactory.CreateWorldStateManagerForTest(dbProvider, NullLogManager.Instance).GlobalWorldState; - _worldStateForContract = TestWorldStateFactory.CreateWorldStateManagerForTest(dbProvider, NullLogManager.Instance).GlobalWorldState; - EthereumCodeInfoRepository codeInfoRepository = new(_worldState); - VirtualMachine virtualMachine = new(new TestBlockhashProvider(_specProvider), _specProvider, LimboLogs.Instance); - _transactionProcessor = new TransactionProcessor(BlobBaseFeeCalculator.Instance, _specProvider, _worldState, virtualMachine, codeInfoRepository, LimboLogs.Instance); - } - [Test] public void MasternodeVotingContract() { PrivateKey sender = TestItem.PrivateKeyA; PrivateKey signer = TestItem.PrivateKeyB; Address codeSource = TestItem.AddressC; - //Save caller in storage slot 0 - var masterVoting = new MasternodeVotingContract(_worldState, new AbiEncoder(), codeSource, new AutoReadOnlyTxProcessingEnv(_transactionProcessor, _worldState, Substitute.For())); + ISpecProvider specProvider = new TestSpecProvider(Shanghai.Instance); + IDbProvider memDbProvider = TestMemDbProvider.Init(); + IWorldState stateProvider = TestWorldStateFactory.CreateForTest(memDbProvider, LimboLogs.Instance); + + IReleaseSpec finalSpec = specProvider.GetFinalSpec(); + + using (var _ = stateProvider.BeginScope(IWorldState.PreGenesis)) + { + stateProvider.CreateAccount(sender.Address, 1.Ether()); + byte[] code = XdcContractData.XDCValidatorBin(); + stateProvider.CreateAccountIfNotExists(codeSource, 0); + stateProvider.InsertCode(codeSource, ValueKeccak.Compute(code), code, Shanghai.Instance); + stateProvider.Commit(specProvider.GenesisSpec); + stateProvider.CommitTree(0); + + var genesis = Build.A.BlockHeader.WithStateRoot(stateProvider.StateRoot).TestObject; + } + + EthereumCodeInfoRepository codeInfoRepository = new(stateProvider); + VirtualMachine virtualMachine = new(new TestBlockhashProvider(specProvider), specProvider, LimboLogs.Instance); + var transactionProcessor = new TransactionProcessor(BlobBaseFeeCalculator.Instance, specProvider, stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); + + //Save caller in storage slot 0 - var scope = _worldState.BeginScope(IWorldState.PreGenesis); - _worldState.CreateAccount(sender.Address, 1.Ether()); - byte[] code = XdcContractData.XDCValidatorBin(); - _worldState.CreateAccountIfNotExists(codeSource, 0); - _worldState.InsertCode(codeSource, ValueKeccak.Compute(code), code, Shanghai.Instance); - _worldState.Commit (Shanghai.Instance, true); + var masterVoting = new MasternodeVotingContract(stateProvider, new AbiEncoder(), codeSource, new AutoReadOnlyTxProcessingEnv(transactionProcessor, stateProvider, Substitute.For())); var header = Build.A.BlockHeader.TestObject; var candidates = masterVoting.GetCandidates(header); From 5861105c617ba6ec43beec96db57a8063393eaf1 Mon Sep 17 00:00:00 2001 From: ak88 Date: Fri, 21 Nov 2025 13:07:46 +0100 Subject: [PATCH 09/25] test getCandidates --- .../Contracts/XdcContractTests.cs | 61 +++++- .../Contracts/MasternodeVotingContract.cs | 3 +- .../Contracts/MasternodeVotingContract.json | 178 ++++++++++++++++++ .../Contracts/XdcContractData.cs | 2 +- 4 files changed, 234 insertions(+), 10 deletions(-) diff --git a/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcContractTests.cs b/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcContractTests.cs index daf26e13b76..cb24f92d33a 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcContractTests.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcContractTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using Autofac; +using FluentAssertions; using Nethermind.Abi; using Nethermind.Blockchain; using Nethermind.Consensus.Processing; @@ -18,6 +19,7 @@ using Nethermind.Evm.State; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; +using Nethermind.Int256; using Nethermind.Logging; using Nethermind.Network; using Nethermind.Specs; @@ -37,7 +39,7 @@ namespace Nethermind.Xdc.Test; internal class XdcContractTests { [Test] - public void MasternodeVotingContract() + public void GetCandidates_GenesisSetup_CanReadExpectedCandidates() { PrivateKey sender = TestItem.PrivateKeyA; PrivateKey signer = TestItem.PrivateKeyB; @@ -48,28 +50,73 @@ public void MasternodeVotingContract() IWorldState stateProvider = TestWorldStateFactory.CreateForTest(memDbProvider, LimboLogs.Instance); IReleaseSpec finalSpec = specProvider.GetFinalSpec(); - + BlockHeader genesis; using (var _ = stateProvider.BeginScope(IWorldState.PreGenesis)) { stateProvider.CreateAccount(sender.Address, 1.Ether()); byte[] code = XdcContractData.XDCValidatorBin(); stateProvider.CreateAccountIfNotExists(codeSource, 0); stateProvider.InsertCode(codeSource, ValueKeccak.Compute(code), code, Shanghai.Instance); + + Dictionary storage = GenesisAllocation(); + foreach (var kvp in storage) + { + StorageCell cell = new(codeSource, UInt256.Parse(kvp.Key)); + stateProvider.Set(cell, Bytes.FromHexString(kvp.Value)); + } + stateProvider.Commit(specProvider.GenesisSpec); stateProvider.CommitTree(0); - var genesis = Build.A.BlockHeader.WithStateRoot(stateProvider.StateRoot).TestObject; + genesis = (XdcBlockHeader)Build.A.XdcBlockHeader().WithStateRoot(stateProvider.StateRoot).TestObject; } EthereumCodeInfoRepository codeInfoRepository = new(stateProvider); VirtualMachine virtualMachine = new(new TestBlockhashProvider(specProvider), specProvider, LimboLogs.Instance); var transactionProcessor = new TransactionProcessor(BlobBaseFeeCalculator.Instance, specProvider, stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); - //Save caller in storage slot 0 - var masterVoting = new MasternodeVotingContract(stateProvider, new AbiEncoder(), codeSource, new AutoReadOnlyTxProcessingEnv(transactionProcessor, stateProvider, Substitute.For())); - var header = Build.A.BlockHeader.TestObject; - var candidates = masterVoting.GetCandidates(header); + var candidates = masterVoting.GetCandidates(genesis); + candidates.Length.Should().Be(3); + } + + private Dictionary GenesisAllocation() + { + return new Dictionary + { + ["0x0000000000000000000000000000000000000000000000000000000000000007"] = "0x0000000000000000000000000000000000000000000000000000000000000001", + ["0x0000000000000000000000000000000000000000000000000000000000000008"] = "0x0000000000000000000000000000000000000000000000000000000000000003", + ["0x0000000000000000000000000000000000000000000000000000000000000009"] = "0x0000000000000000000000000000000000000000000000000000000000000003", + ["0x000000000000000000000000000000000000000000000000000000000000000a"] = "0x0000000000000000000000000000000000000000000000000000000000000001", + ["0x000000000000000000000000000000000000000000000000000000000000000b"] = "0x000000000000000000000000000000000000000000084595161401484a000000", + ["0x000000000000000000000000000000000000000000000000000000000000000c"] = "0x00000000000000000000000000000000000000000000054b40b1f852bda00000", + ["0x000000000000000000000000000000000000000000000000000000000000000d"] = "0x0000000000000000000000000000000000000000000000000000000000000012", + ["0x000000000000000000000000000000000000000000000000000000000000000e"] = "0x000000000000000000000000000000000000000000000000000000000013c680", + ["0x000000000000000000000000000000000000000000000000000000000000000f"] = "0x0000000000000000000000000000000000000000000000000000000000069780", + ["0x1cb68bf63bb3b55abf504ef789bb06e8b2b266a334ca39892e163225a47b8267"] = "0x000000000000000000000000000000000000000000084595161401484a000000", + ["0x2c6b8fd5b2b39958a7e5a98eebf2c1c31122e89c7961ce1025e69a3d3f07fd20"] = "0x0000000000000000000000000000000000000000000000000000000000000001", + ["0x3639e2dfabac2c6baff147abd66f76b8e526e974a9a2a14163169aa03d2f8d4b"] = "0x0000000000000000000000000000000000000000000000000000000000000001", + ["0x473ba2a6d1aa200b3118a8abc51fe248a479e882e6c655ae014d9c66fbc181ed"] = "0x00000000000000000000000025c65b4b379ac37cf78357c4915f73677022eaff", + ["0x473ba2a6d1aa200b3118a8abc51fe248a479e882e6c655ae014d9c66fbc181ee"] = "0x000000000000000000000000c7d49d0a2cf198deebd6ce581af465944ec8b2bb", + ["0x473ba2a6d1aa200b3118a8abc51fe248a479e882e6c655ae014d9c66fbc181ef"] = "0x000000000000000000000000cfccdea1006a5cfa7d9484b5b293b46964c265c0", + ["0x53dbb2c13e64ef254df4bb7c7b541e84dd24870927f98f151db88daa464fb4dc"] = "0x000000000000000000000000381047523972c9fdc3aa343e0b96900a8e2fa765", + ["0x67a3292220e327ce969d100d7e4d83dd4b05efa763a5e4cdb04e0c0107736472"] = "0x000000000000000000000001381047523972c9fdc3aa343e0b96900a8e2fa765", + ["0x67a3292220e327ce969d100d7e4d83dd4b05efa763a5e4cdb04e0c0107736473"] = "0x000000000000000000000000000000000000000000084595161401484a000000", + ["0x78dfe8da08db00fe2cd4ddbd11f9cb7e4245ce35275d7734678593942034e181"] = "0x000000000000000000000001381047523972c9fdc3aa343e0b96900a8e2fa765", + ["0x78dfe8da08db00fe2cd4ddbd11f9cb7e4245ce35275d7734678593942034e182"] = "0x000000000000000000000000000000000000000000084595161401484a000000", + ["0x90e333b6971c3ecd09a0da09b031d63cdd2dc213d199a66955a8bf7df8a8142d"] = "0x000000000000000000000000000000000000000000084595161401484a000000", + ["0xa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688"] = "0x000000000000000000000000381047523972c9fdc3aa343e0b96900a8e2fa765", + ["0xac80bed7555f6f181a34915490d97d0bfe2c0e116d1c73b34523ca0d9749955c"] = "0x000000000000000000000000381047523972c9fdc3aa343e0b96900a8e2fa765", + ["0xae7e2a864ae923819e93a9f6183bc7ca0dcee93a0759238acd92344ad3216228"] = "0x000000000000000000000000000000000000000000084595161401484a000000", + ["0xb375859c4c97d60e8a699586dc5dd215f38f99e40430bb9261f085ee694ffb2c"] = "0x0000000000000000000000000000000000000000000000000000000000000001", + ["0xd5d5b62da76a3a9f2df0e9276cbaf8973a778bf41f7f4942e06243f195493e99"] = "0x000000000000000000000000381047523972c9fdc3aa343e0b96900a8e2fa765", + ["0xec8699f61c2c8bbdbc66463590788e526c60046dda98e8c70df1fb756050baa4"] = "0x0000000000000000000000000000000000000000000000000000000000000003", + ["0xf3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee3"] = "0x00000000000000000000000025c65b4b379ac37cf78357c4915f73677022eaff", + ["0xf3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee4"] = "0x000000000000000000000000c7d49d0a2cf198deebd6ce581af465944ec8b2bb", + ["0xf3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee5"] = "0x000000000000000000000000cfccdea1006a5cfa7d9484b5b293b46964c265c0", + ["0xf4dd36495f675c407ac8f8d6dd8cc40162c854dba3ce4ce8919af34d0b1ed47c"] = "0x000000000000000000000001381047523972c9fdc3aa343e0b96900a8e2fa765", + ["0xf4dd36495f675c407ac8f8d6dd8cc40162c854dba3ce4ce8919af34d0b1ed47d"] = "0x000000000000000000000000000000000000000000084595161401484a000000" + }; } } diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs index f738a06c9dd..005a0ed3376 100644 --- a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs +++ b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs @@ -17,7 +17,6 @@ namespace Nethermind.Xdc.Contracts; internal class MasternodeVotingContract : Contract, IMasternodeVotingContract { private readonly IWorldState _worldState; - private IConstantContract _constant; public MasternodeVotingContract( @@ -51,7 +50,7 @@ public Address[] GetCandidates(BlockHeader blockHeader) { var callInfo = new CallInfo(blockHeader, "getCandidates", Address.SystemUser); var result = this._constant.Call(callInfo); - return (Address[])result!; + return (Address[])result[0]!; } /// diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.json b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.json index 828f4975ab8..4a20ad6ee49 100644 --- a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.json +++ b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.json @@ -545,5 +545,183 @@ "payable": false, "stateMutability": "view", "type": "function" + }, + { + "inputs": [ + { + "name": "_candidates", + "type": "address[]" + }, + { + "name": "_caps", + "type": "uint256[]" + }, + { + "name": "_firstOwner", + "type": "address" + }, + { + "name": "_minCandidateCap", + "type": "uint256" + }, + { + "name": "_minVoterCap", + "type": "uint256" + }, + { + "name": "_maxValidatorNumber", + "type": "uint256" + }, + { + "name": "_candidateWithdrawDelay", + "type": "uint256" + }, + { + "name": "_voterWithdrawDelay", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "_voter", + "type": "address" + }, + { + "indexed": false, + "name": "_candidate", + "type": "address" + }, + { + "indexed": false, + "name": "_cap", + "type": "uint256" + } + ], + "name": "Vote", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "_voter", + "type": "address" + }, + { + "indexed": false, + "name": "_candidate", + "type": "address" + }, + { + "indexed": false, + "name": "_cap", + "type": "uint256" + } + ], + "name": "Unvote", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "_owner", + "type": "address" + }, + { + "indexed": false, + "name": "_candidate", + "type": "address" + }, + { + "indexed": false, + "name": "_cap", + "type": "uint256" + } + ], + "name": "Propose", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "_owner", + "type": "address" + }, + { + "indexed": false, + "name": "_candidate", + "type": "address" + } + ], + "name": "Resign", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "_owner", + "type": "address" + }, + { + "indexed": false, + "name": "_blockNumber", + "type": "uint256" + }, + { + "indexed": false, + "name": "_cap", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "_owner", + "type": "address" + }, + { + "indexed": false, + "name": "kycHash", + "type": "string" + } + ], + "name": "UploadedKYC", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "_masternodeOwner", + "type": "address" + }, + { + "indexed": false, + "name": "_masternodes", + "type": "address[]" + } + ], + "name": "InvalidatedNode", + "type": "event" } ] diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/XdcContractData.cs b/src/Nethermind/Nethermind.Xdc/Contracts/XdcContractData.cs index 7b7bed0f984..25938379f9b 100644 --- a/src/Nethermind/Nethermind.Xdc/Contracts/XdcContractData.cs +++ b/src/Nethermind/Nethermind.Xdc/Contracts/XdcContractData.cs @@ -12,5 +12,5 @@ namespace Nethermind.Xdc.Contracts; internal static class XdcContractData { // XDCValidatorBin is the compiled bytecode used for deploying new contracts. - public static byte[] XDCValidatorBin() => Bytes.FromHexString("0x606060405260006009556000600a5534156200001a57600080fd5b60405162003dcc38038062003dcc83398101604052808051820191906020018051820191906020018051906020019091908051906020019091908051906020019091908051906020019091908051906020019091908051906020019091905050600085600b8190555084600c8190555083600d8190555082600e8190555081600f81905550885160098190555060078054806001018281620000bd9190620004f1565b9160005260206000209001600089909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600a60008154809291906001019190505550600090505b8851811015620004e25760088054806001018281620001439190620004f1565b916000526020600020900160008b848151811015156200015f57fe5b90602001906020020151909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506060604051908101604052808873ffffffffffffffffffffffffffffffffffffffff1681526020016001151581526020018983815181101515620001ea57fe5b90602001906020020151815250600160008b848151811015156200020a57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548160ff02191690831515021790555060408201518160010155905050600260008a83815181101515620002d557fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816200032d9190620004f1565b9160005260206000209001600089909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281620003cf9190620004f1565b916000526020600020900160008b84815181101515620003eb57fe5b90602001906020020151909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600b54600160008b848151811015156200044c57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550808060010191505062000123565b50505050505050505062000548565b8154818355818115116200051b578183600052602060002091820191016200051a919062000520565b5b505050565b6200054591905b808211156200054157600081600090555060010162000527565b5090565b90565b61387480620005586000396000f300606060405260043610610196576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063012679511461019b578063025e7c27146101c957806302aa9be21461022c57806306a49fce1461026e5780630db02622146102d85780630e3e4fb81461030157806315febd68146103715780632a3640b1146103a85780632d15cc041461042a5780632f9c4bba146104b8578063302b687214610522578063326586521461058e5780633477ee2e14610640578063441a3e70146106a357806358e7525f146106cf5780635b860d271461071c5780635b9cd8cc146107695780636dd7d8ea1461082457806372e44a3814610852578063a9a981a31461089f578063a9ff959e146108c8578063ae6e43f5146108f1578063b642facd1461092a578063c45607df146109a3578063d09f1ab4146109f0578063d161c76714610a19578063d51b9e9314610a42578063d55b7dff14610a93578063ef18374a14610abc578063f2ee3c7d14610ae5578063f5c9512514610b1e578063f8ac9dd514610b4c575b600080fd5b6101c7600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610b75565b005b34156101d457600080fd5b6101ea60048080359060200190919050506111fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561023757600080fd5b61026c600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061123b565b005b341561027957600080fd5b610281611796565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102c45780820151818401526020810190506102a9565b505050509050019250505060405180910390f35b34156102e357600080fd5b6102eb61182a565b6040518082815260200191505060405180910390f35b341561030c57600080fd5b610357600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611830565b604051808215151515815260200191505060405180910390f35b341561037c57600080fd5b610392600480803590602001909190505061185f565b6040518082815260200191505060405180910390f35b34156103b357600080fd5b6103e8600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506118bb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561043557600080fd5b610461600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611909565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156104a4578082015181840152602081019050610489565b505050509050019250505060405180910390f35b34156104c357600080fd5b6104cb6119dc565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561050e5780820151818401526020810190506104f3565b505050509050019250505060405180910390f35b341561052d57600080fd5b610578600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611a79565b6040518082815260200191505060405180910390f35b341561059957600080fd5b6105c5600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611b03565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156106055780820151818401526020810190506105ea565b50505050905090810190601f1680156106325780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561064b57600080fd5b6106616004808035906020019091905050611da2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156106ae57600080fd5b6106cd6004808035906020019091908035906020019091905050611de1565b005b34156106da57600080fd5b610706600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061208d565b6040518082815260200191505060405180910390f35b341561072757600080fd5b610753600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506120d9565b6040518082815260200191505060405180910390f35b341561077457600080fd5b6107a9600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506121a1565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156107e95780820151818401526020810190506107ce565b50505050905090810190601f1680156108165780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610850600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061226a565b005b341561085d57600080fd5b610889600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612653565b6040518082815260200191505060405180910390f35b34156108aa57600080fd5b6108b261266b565b6040518082815260200191505060405180910390f35b34156108d357600080fd5b6108db612671565b6040518082815260200191505060405180910390f35b34156108fc57600080fd5b610928600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612677565b005b341561093557600080fd5b610961600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612c36565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156109ae57600080fd5b6109da600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612ca2565b6040518082815260200191505060405180910390f35b34156109fb57600080fd5b610a03612cee565b6040518082815260200191505060405180910390f35b3415610a2457600080fd5b610a2c612cf4565b6040518082815260200191505060405180910390f35b3415610a4d57600080fd5b610a79600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612cfa565b604051808215151515815260200191505060405180910390f35b3415610a9e57600080fd5b610aa6612d53565b6040518082815260200191505060405180910390f35b3415610ac757600080fd5b610acf612d59565b6040518082815260200191505060405180910390f35b3415610af057600080fd5b610b1c600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612d63565b005b3415610b2957600080fd5b610b4a600480803590602001908201803590602001919091929050506134f1565b005b3415610b5757600080fd5b610b5f6135f0565b6040518082815260200191505060405180910390f35b6000600b543410151515610b8857600080fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050141580610c1c57506000600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050115b1515610c2757600080fd5b81600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff16151515610c8457600080fd5b610cd934600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101546135f690919063ffffffff16565b915060088054806001018281610cef919061362d565b9160005260206000209001600085909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506060604051908101604052803373ffffffffffffffffffffffffffffffffffffffff16815260200160011515815260200183815250600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548160ff02191690831515021790555060408201518160010155905050610eb834600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546135f690919063ffffffff16565b600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610f5160016009546135f690919063ffffffff16565b6009819055506000600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905014156110185760078054806001018281610fb6919061362d565b9160005260206000209001600033909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600a600081548092919060010191905055505b600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281611069919061362d565b9160005260206000209001600085909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281611109919061362d565b9160005260206000209001600033909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550507f7635f1d87b47fba9f2b09e56eb4be75cca030e0cb179c1602ac9261d39a8f5c1338434604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a1505050565b60078181548110151561120b57fe5b90600052602060002090016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000828280600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156112cd57600080fd5b3373ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561140657600b546113f882600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461361490919063ffffffff16565b1015151561140557600080fd5b5b61145b84600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015461361490919063ffffffff16565b600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018190555061153384600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461361490919063ffffffff16565b600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506115cb43600f546135f690919063ffffffff16565b9250611632846000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000868152602001908152602001600020546135f690919063ffffffff16565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000858152602001908152602001600020819055506000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010180548060010182816116db9190613659565b9160005260206000209001600085909190915055507faa0e554f781c3c3b2be110a0557f260f11af9a8aa2c64bc1e7a31dbb21e32fa2338686604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a15050505050565b61179e613685565b600880548060200260200160405190810160405280929190818152602001828054801561182057602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116117d6575b5050505050905090565b600a5481565b60056020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60008060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000838152602001908152602001600020549050919050565b6006602052816000526040600020818154811015156118d657fe5b90600052602060002090016000915091509054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611911613685565b600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156119d057602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311611986575b50505050509050919050565b6119e4613699565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101805480602002602001604051908101604052809291908181526020018280548015611a6f57602002820191906000526020600020905b815481526020019060010190808311611a5b575b5050505050905090565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b611b0b6136ad565b611b1482612cfa565b15611c655760036000611b2684612c36565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600160036000611b6f86612c36565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905003815481101515611bba57fe5b90600052602060002090018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611c595780601f10611c2e57610100808354040283529160200191611c59565b820191906000526020600020905b815481529060010190602001808311611c3c57829003601f168201915b50505050509050611d9d565b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905003815481101515611cf657fe5b90600052602060002090018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611d955780601f10611d6a57610100808354040283529160200191611d95565b820191906000526020600020905b815481529060010190602001808311611d7857829003601f168201915b505050505090505b919050565b600881815481101515611db157fe5b90600052602060002090016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008282600082111515611df457600080fd5b814310151515611e0357600080fd5b60008060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001600084815260200190815260200160002054111515611e6457600080fd5b816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010182815481101515611eb357fe5b906000526020600020900154141515611ecb57600080fd5b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008681526020019081526020016000205492506000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000868152602001908152602001600020600090556000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010184815481101515611fc457fe5b9060005260206000209001600090553373ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f19350505050151561201357600080fd5b7ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568338685604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390a15050505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101549050919050565b60008082600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff16151561213857600080fd5b61214184612c36565b915061214b612d59565b6064600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540281151561219757fe5b0492505050919050565b6003602052816000526040600020818154811015156121bc57fe5b9060005260206000209001600091509150508054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156122625780601f1061223757610100808354040283529160200191612262565b820191906000526020600020905b81548152906001019060200180831161224557829003601f168201915b505050505081565b600c54341015151561227b57600080fd5b80600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff1615156122d757600080fd5b61232c34600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101546135f690919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054141561249b57600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161244b919061362d565b9160005260206000209001600033909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505b61252d34600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546135f690919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507f66a9138482c99e9baf08860110ef332cc0c23b4a199a53593d8db0fc8f96fbfc338334604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a15050565b60046020528060005260406000206000915090505481565b60095481565b600f5481565b6000806000833373ffffffffffffffffffffffffffffffffffffffff16600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151561271957600080fd5b84600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff16151561277557600080fd5b6000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160146101000a81548160ff0219169083151502179055506127e6600160095461361490919063ffffffff16565b600981905550600094505b6008805490508510156128bb578573ffffffffffffffffffffffffffffffffffffffff1660088681548110151561282457fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156128ae5760088581548110151561287b57fe5b906000526020600020900160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556128bb565b84806001019550506127f1565b600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054935061299284600160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015461361490919063ffffffff16565b600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550612a7243600e546135f690919063ffffffff16565b9250612ad9846000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000868152602001908152602001600020546135f690919063ffffffff16565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000858152602001908152602001600020819055506000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018054806001018281612b829190613659565b9160005260206000209001600085909190915055507f4edf3e325d0063213a39f9085522994a1c44bea5f39e7d63ef61260a1e58c6d33387604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a1505050505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050919050565b600d5481565b600e5481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff169050919050565b600b5481565b6000600a54905090565b600080612d6e613685565b600080600033600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff161515612dcf57600080fd5b87600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff161515612e2b57600080fd5b612e3433612c36565b9750612e3f89612c36565b9650600560008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515612ed757600080fd5b6001600560008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600460008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550604b612fc4612d59565b6064600460008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540281151561301057fe5b041015156134e65760016008805490500360405180591061302e5750595b9080825280602002602001820160405250955060009450600093505b600880549050841015613357578673ffffffffffffffffffffffffffffffffffffffff166130b160088681548110151561308057fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16612c36565b73ffffffffffffffffffffffffffffffffffffffff16141561334a576130e3600160095461361490919063ffffffff16565b6009819055506008848154811015156130f857fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16868680600101975081518110151561313857fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060088481548110151561318357fe5b906000526020600020900160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600160006008868154811015156131c457fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000820160146101000a81549060ff021916905560018201600090555050600360008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006132bb91906136c1565b600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061330691906136e2565b600460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600090555b838060010194505061304a565b600092505b600780549050831015613439578673ffffffffffffffffffffffffffffffffffffffff1660078481548110151561338f57fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561342c576007838154811015156133e657fe5b906000526020600020900160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600a6000815480929190600190039190505550613439565b828060010193505061335c565b7fe18d61a5bf4aa2ab40afc88aa9039d27ae17ff4ec1c65f5f414df6f02ce8b35e8787604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019060200280838360005b838110156134d15780820151818401526020810190506134b6565b50505050905001935050505060405180910390a15b505050505050505050565b600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816135429190613703565b91600052602060002090016000848490919290919250919061356592919061372f565b50507f949360d814b28a3b393a68909efe1fee120ee09cac30f360a0f80ab5415a611a338383604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001806020018281038252848482818152602001925080828437820191505094505050505060405180910390a15050565b600c5481565b600080828401905083811015151561360a57fe5b8091505092915050565b600082821115151561362257fe5b818303905092915050565b8154818355818115116136545781836000526020600020918201910161365391906137af565b5b505050565b8154818355818115116136805781836000526020600020918201910161367f91906137af565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b50805460008255906000526020600020908101906136df91906137d4565b50565b508054600082559060005260206000209081019061370091906137af565b50565b81548183558181151161372a5781836000526020600020918201910161372991906137d4565b5b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061377057803560ff191683800117855561379e565b8280016001018555821561379e579182015b8281111561379d578235825591602001919060010190613782565b5b5090506137ab91906137af565b5090565b6137d191905b808211156137cd5760008160009055506001016137b5565b5090565b90565b6137fd91905b808211156137f957600081816137f09190613800565b506001016137da565b5090565b90565b50805460018160011615610100020316600290046000825580601f106138265750613845565b601f01602090049060005260206000209081019061384491906137af565b5b505600a165627a7a72305820f5bbb127b52ce86c873faef85cff176563476a5e49a3d88eaa9a06a8f432c9080029"); + public static byte[] XDCValidatorBin() => Bytes.FromHexString("606060405260043610610196576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063012679511461019b578063025e7c27146101c957806302aa9be21461022c57806306a49fce1461026e5780630db02622146102d85780630e3e4fb81461030157806315febd68146103715780632a3640b1146103a85780632d15cc041461042a5780632f9c4bba146104b8578063302b687214610522578063326586521461058e5780633477ee2e14610640578063441a3e70146106a357806358e7525f146106cf5780635b860d271461071c5780635b9cd8cc146107695780636dd7d8ea1461082457806372e44a3814610852578063a9a981a31461089f578063a9ff959e146108c8578063ae6e43f5146108f1578063b642facd1461092a578063c45607df146109a3578063d09f1ab4146109f0578063d161c76714610a19578063d51b9e9314610a42578063d55b7dff14610a93578063ef18374a14610abc578063f2ee3c7d14610ae5578063f5c9512514610b1e578063f8ac9dd514610b4c575b600080fd5b6101c7600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610b75565b005b34156101d457600080fd5b6101ea60048080359060200190919050506111fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561023757600080fd5b61026c600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061123b565b005b341561027957600080fd5b610281611796565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102c45780820151818401526020810190506102a9565b505050509050019250505060405180910390f35b34156102e357600080fd5b6102eb61182a565b6040518082815260200191505060405180910390f35b341561030c57600080fd5b610357600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611830565b604051808215151515815260200191505060405180910390f35b341561037c57600080fd5b610392600480803590602001909190505061185f565b6040518082815260200191505060405180910390f35b34156103b357600080fd5b6103e8600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506118bb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561043557600080fd5b610461600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611909565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156104a4578082015181840152602081019050610489565b505050509050019250505060405180910390f35b34156104c357600080fd5b6104cb6119dc565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561050e5780820151818401526020810190506104f3565b505050509050019250505060405180910390f35b341561052d57600080fd5b610578600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611a79565b6040518082815260200191505060405180910390f35b341561059957600080fd5b6105c5600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611b03565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156106055780820151818401526020810190506105ea565b50505050905090810190601f1680156106325780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561064b57600080fd5b6106616004808035906020019091905050611da2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156106ae57600080fd5b6106cd6004808035906020019091908035906020019091905050611de1565b005b34156106da57600080fd5b610706600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061208d565b6040518082815260200191505060405180910390f35b341561072757600080fd5b610753600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506120d9565b6040518082815260200191505060405180910390f35b341561077457600080fd5b6107a9600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506121a1565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156107e95780820151818401526020810190506107ce565b50505050905090810190601f1680156108165780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610850600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061226a565b005b341561085d57600080fd5b610889600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612653565b6040518082815260200191505060405180910390f35b34156108aa57600080fd5b6108b261266b565b6040518082815260200191505060405180910390f35b34156108d357600080fd5b6108db612671565b6040518082815260200191505060405180910390f35b34156108fc57600080fd5b610928600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612677565b005b341561093557600080fd5b610961600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612c36565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156109ae57600080fd5b6109da600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612ca2565b6040518082815260200191505060405180910390f35b34156109fb57600080fd5b610a03612cee565b6040518082815260200191505060405180910390f35b3415610a2457600080fd5b610a2c612cf4565b6040518082815260200191505060405180910390f35b3415610a4d57600080fd5b610a79600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612cfa565b604051808215151515815260200191505060405180910390f35b3415610a9e57600080fd5b610aa6612d53565b6040518082815260200191505060405180910390f35b3415610ac757600080fd5b610acf612d59565b6040518082815260200191505060405180910390f35b3415610af057600080fd5b610b1c600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612d63565b005b3415610b2957600080fd5b610b4a600480803590602001908201803590602001919091929050506134f1565b005b3415610b5757600080fd5b610b5f6135f0565b6040518082815260200191505060405180910390f35b6000600b543410151515610b8857600080fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050141580610c1c57506000600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050115b1515610c2757600080fd5b81600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff16151515610c8457600080fd5b610cd934600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101546135f690919063ffffffff16565b915060088054806001018281610cef919061362d565b9160005260206000209001600085909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506060604051908101604052803373ffffffffffffffffffffffffffffffffffffffff16815260200160011515815260200183815250600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548160ff02191690831515021790555060408201518160010155905050610eb834600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546135f690919063ffffffff16565b600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610f5160016009546135f690919063ffffffff16565b6009819055506000600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905014156110185760078054806001018281610fb6919061362d565b9160005260206000209001600033909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600a600081548092919060010191905055505b600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281611069919061362d565b9160005260206000209001600085909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281611109919061362d565b9160005260206000209001600033909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550507f7635f1d87b47fba9f2b09e56eb4be75cca030e0cb179c1602ac9261d39a8f5c1338434604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a1505050565b60078181548110151561120b57fe5b90600052602060002090016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000828280600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156112cd57600080fd5b3373ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561140657600b546113f882600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461361490919063ffffffff16565b1015151561140557600080fd5b5b61145b84600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015461361490919063ffffffff16565b600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018190555061153384600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461361490919063ffffffff16565b600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506115cb43600f546135f690919063ffffffff16565b9250611632846000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000868152602001908152602001600020546135f690919063ffffffff16565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000858152602001908152602001600020819055506000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010180548060010182816116db9190613659565b9160005260206000209001600085909190915055507faa0e554f781c3c3b2be110a0557f260f11af9a8aa2c64bc1e7a31dbb21e32fa2338686604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a15050505050565b61179e613685565b600880548060200260200160405190810160405280929190818152602001828054801561182057602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116117d6575b5050505050905090565b600a5481565b60056020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60008060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000838152602001908152602001600020549050919050565b6006602052816000526040600020818154811015156118d657fe5b90600052602060002090016000915091509054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611911613685565b600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156119d057602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311611986575b50505050509050919050565b6119e4613699565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101805480602002602001604051908101604052809291908181526020018280548015611a6f57602002820191906000526020600020905b815481526020019060010190808311611a5b575b5050505050905090565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b611b0b6136ad565b611b1482612cfa565b15611c655760036000611b2684612c36565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600160036000611b6f86612c36565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905003815481101515611bba57fe5b90600052602060002090018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611c595780601f10611c2e57610100808354040283529160200191611c59565b820191906000526020600020905b815481529060010190602001808311611c3c57829003601f168201915b50505050509050611d9d565b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905003815481101515611cf657fe5b90600052602060002090018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611d955780601f10611d6a57610100808354040283529160200191611d95565b820191906000526020600020905b815481529060010190602001808311611d7857829003601f168201915b505050505090505b919050565b600881815481101515611db157fe5b90600052602060002090016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008282600082111515611df457600080fd5b814310151515611e0357600080fd5b60008060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001600084815260200190815260200160002054111515611e6457600080fd5b816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010182815481101515611eb357fe5b906000526020600020900154141515611ecb57600080fd5b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008681526020019081526020016000205492506000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000868152602001908152602001600020600090556000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010184815481101515611fc457fe5b9060005260206000209001600090553373ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f19350505050151561201357600080fd5b7ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568338685604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390a15050505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101549050919050565b60008082600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff16151561213857600080fd5b61214184612c36565b915061214b612d59565b6064600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540281151561219757fe5b0492505050919050565b6003602052816000526040600020818154811015156121bc57fe5b9060005260206000209001600091509150508054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156122625780601f1061223757610100808354040283529160200191612262565b820191906000526020600020905b81548152906001019060200180831161224557829003601f168201915b505050505081565b600c54341015151561227b57600080fd5b80600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff1615156122d757600080fd5b61232c34600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101546135f690919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054141561249b57600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161244b919061362d565b9160005260206000209001600033909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505b61252d34600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546135f690919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507f66a9138482c99e9baf08860110ef332cc0c23b4a199a53593d8db0fc8f96fbfc338334604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a15050565b60046020528060005260406000206000915090505481565b60095481565b600f5481565b6000806000833373ffffffffffffffffffffffffffffffffffffffff16600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151561271957600080fd5b84600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff16151561277557600080fd5b6000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160146101000a81548160ff0219169083151502179055506127e6600160095461361490919063ffffffff16565b600981905550600094505b6008805490508510156128bb578573ffffffffffffffffffffffffffffffffffffffff1660088681548110151561282457fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156128ae5760088581548110151561287b57fe5b906000526020600020900160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556128bb565b84806001019550506127f1565b600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054935061299284600160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015461361490919063ffffffff16565b600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550612a7243600e546135f690919063ffffffff16565b9250612ad9846000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000868152602001908152602001600020546135f690919063ffffffff16565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000858152602001908152602001600020819055506000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018054806001018281612b829190613659565b9160005260206000209001600085909190915055507f4edf3e325d0063213a39f9085522994a1c44bea5f39e7d63ef61260a1e58c6d33387604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a1505050505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050919050565b600d5481565b600e5481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff169050919050565b600b5481565b6000600a54905090565b600080612d6e613685565b600080600033600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff161515612dcf57600080fd5b87600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff161515612e2b57600080fd5b612e3433612c36565b9750612e3f89612c36565b9650600560008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515612ed757600080fd5b6001600560008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600460008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550604b612fc4612d59565b6064600460008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540281151561301057fe5b041015156134e65760016008805490500360405180591061302e5750595b9080825280602002602001820160405250955060009450600093505b600880549050841015613357578673ffffffffffffffffffffffffffffffffffffffff166130b160088681548110151561308057fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16612c36565b73ffffffffffffffffffffffffffffffffffffffff16141561334a576130e3600160095461361490919063ffffffff16565b6009819055506008848154811015156130f857fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16868680600101975081518110151561313857fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060088481548110151561318357fe5b906000526020600020900160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600160006008868154811015156131c457fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000820160146101000a81549060ff021916905560018201600090555050600360008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006132bb91906136c1565b600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061330691906136e2565b600460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600090555b838060010194505061304a565b600092505b600780549050831015613439578673ffffffffffffffffffffffffffffffffffffffff1660078481548110151561338f57fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561342c576007838154811015156133e657fe5b906000526020600020900160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600a6000815480929190600190039190505550613439565b828060010193505061335c565b7fe18d61a5bf4aa2ab40afc88aa9039d27ae17ff4ec1c65f5f414df6f02ce8b35e8787604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019060200280838360005b838110156134d15780820151818401526020810190506134b6565b50505050905001935050505060405180910390a15b505050505050505050565b600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816135429190613703565b91600052602060002090016000848490919290919250919061356592919061372f565b50507f949360d814b28a3b393a68909efe1fee120ee09cac30f360a0f80ab5415a611a338383604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001806020018281038252848482818152602001925080828437820191505094505050505060405180910390a15050565b600c5481565b600080828401905083811015151561360a57fe5b8091505092915050565b600082821115151561362257fe5b818303905092915050565b8154818355818115116136545781836000526020600020918201910161365391906137af565b5b505050565b8154818355818115116136805781836000526020600020918201910161367f91906137af565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b50805460008255906000526020600020908101906136df91906137d4565b50565b508054600082559060005260206000209081019061370091906137af565b50565b81548183558181151161372a5781836000526020600020918201910161372991906137d4565b5b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061377057803560ff191683800117855561379e565b8280016001018555821561379e579182015b8281111561379d578235825591602001919060010190613782565b5b5090506137ab91906137af565b5090565b6137d191905b808211156137cd5760008160009055506001016137b5565b5090565b90565b6137fd91905b808211156137f957600081816137f09190613800565b506001016137da565b5090565b90565b50805460018160011615610100020316600290046000825580601f106138265750613845565b601f01602090049060005260206000209081019061384491906137af565b5b505600a165627a7a72305820f5bbb127b52ce86c873faef85cff176563476a5e49a3d88eaa9a06a8f432c9080029"); } From c157ad006693bd942f249132a769d0a025f773cc Mon Sep 17 00:00:00 2001 From: ak88 Date: Fri, 21 Nov 2025 13:16:20 +0100 Subject: [PATCH 10/25] cleanup --- ...ts.cs => MasternodeVotingContractTests.cs} | 29 +++++++++---------- .../Contracts/MasternodeVotingContract.cs | 2 +- 2 files changed, 15 insertions(+), 16 deletions(-) rename src/Nethermind/Nethermind.Xdc.Test/Contracts/{XdcContractTests.cs => MasternodeVotingContractTests.cs} (87%) diff --git a/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcContractTests.cs b/src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs similarity index 87% rename from src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcContractTests.cs rename to src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs index cb24f92d33a..be410ab4d53 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcContractTests.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs @@ -5,7 +5,6 @@ using FluentAssertions; using Nethermind.Abi; using Nethermind.Blockchain; -using Nethermind.Consensus.Processing; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; @@ -17,29 +16,23 @@ using Nethermind.Db; using Nethermind.Evm; using Nethermind.Evm.State; -using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Int256; using Nethermind.Logging; -using Nethermind.Network; using Nethermind.Specs; using Nethermind.Specs.Forks; -using Nethermind.State; using Nethermind.Xdc.Contracts; using NSubstitute; using NUnit.Framework; using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using static Nethermind.Consensus.Processing.AutoReadOnlyTxProcessingEnvFactory; namespace Nethermind.Xdc.Test; -internal class XdcContractTests +internal class MasternodeVotingContractTests { [Test] - public void GetCandidates_GenesisSetup_CanReadExpectedCandidates() + public void GetCandidatesAndStake_GenesisSetup_CanReadExpectedCandidates() { PrivateKey sender = TestItem.PrivateKeyA; PrivateKey signer = TestItem.PrivateKeyB; @@ -51,7 +44,7 @@ public void GetCandidates_GenesisSetup_CanReadExpectedCandidates() IReleaseSpec finalSpec = specProvider.GetFinalSpec(); BlockHeader genesis; - using (var _ = stateProvider.BeginScope(IWorldState.PreGenesis)) + using (IDisposable _ = stateProvider.BeginScope(IWorldState.PreGenesis)) { stateProvider.CreateAccount(sender.Address, 1.Ether()); byte[] code = XdcContractData.XDCValidatorBin(); @@ -59,7 +52,7 @@ public void GetCandidates_GenesisSetup_CanReadExpectedCandidates() stateProvider.InsertCode(codeSource, ValueKeccak.Compute(code), code, Shanghai.Instance); Dictionary storage = GenesisAllocation(); - foreach (var kvp in storage) + foreach (KeyValuePair kvp in storage) { StorageCell cell = new(codeSource, UInt256.Parse(kvp.Key)); stateProvider.Set(cell, Bytes.FromHexString(kvp.Value)); @@ -68,17 +61,23 @@ public void GetCandidates_GenesisSetup_CanReadExpectedCandidates() stateProvider.Commit(specProvider.GenesisSpec); stateProvider.CommitTree(0); - genesis = (XdcBlockHeader)Build.A.XdcBlockHeader().WithStateRoot(stateProvider.StateRoot).TestObject; + genesis = Build.A.XdcBlockHeader().WithStateRoot(stateProvider.StateRoot).TestObject; } EthereumCodeInfoRepository codeInfoRepository = new(stateProvider); VirtualMachine virtualMachine = new(new TestBlockhashProvider(specProvider), specProvider, LimboLogs.Instance); - var transactionProcessor = new TransactionProcessor(BlobBaseFeeCalculator.Instance, specProvider, stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); + TransactionProcessor transactionProcessor = new (BlobBaseFeeCalculator.Instance, specProvider, stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); - var masterVoting = new MasternodeVotingContract(stateProvider, new AbiEncoder(), codeSource, new AutoReadOnlyTxProcessingEnv(transactionProcessor, stateProvider, Substitute.For())); + MasternodeVotingContract masterVoting = new (stateProvider, new AbiEncoder(), codeSource, new AutoReadOnlyTxProcessingEnv(transactionProcessor, stateProvider, Substitute.For())); - var candidates = masterVoting.GetCandidates(genesis); + Address[] candidates = masterVoting.GetCandidates(genesis); candidates.Length.Should().Be(3); + + foreach (Address candidate in candidates) + { + UInt256 stake = masterVoting.GetCandidateStake(genesis, candidate); + stake.Should().Be(10_000_000.Ether()); + } } private Dictionary GenesisAllocation() diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs index 005a0ed3376..52a91017c1a 100644 --- a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs +++ b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs @@ -58,7 +58,7 @@ public Address[] GetCandidates(BlockHeader blockHeader) /// /// /// - public Address[] GetCandidates(XdcBlockHeader header) + public Address[] GetCandidatesFromState(BlockHeader header) { var variableSlot = CandidateContractSlots.Candidates; Span input = [(byte)variableSlot]; From 840b59d0908ae1c56b2d12fb9fc6b12a218b77fe Mon Sep 17 00:00:00 2001 From: ak88 Date: Fri, 21 Nov 2025 13:18:32 +0100 Subject: [PATCH 11/25] format --- .../Contracts/MasternodeVotingContractTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs b/src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs index be410ab4d53..4c86dade68b 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs @@ -66,9 +66,9 @@ public void GetCandidatesAndStake_GenesisSetup_CanReadExpectedCandidates() EthereumCodeInfoRepository codeInfoRepository = new(stateProvider); VirtualMachine virtualMachine = new(new TestBlockhashProvider(specProvider), specProvider, LimboLogs.Instance); - TransactionProcessor transactionProcessor = new (BlobBaseFeeCalculator.Instance, specProvider, stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); + TransactionProcessor transactionProcessor = new(BlobBaseFeeCalculator.Instance, specProvider, stateProvider, virtualMachine, codeInfoRepository, LimboLogs.Instance); - MasternodeVotingContract masterVoting = new (stateProvider, new AbiEncoder(), codeSource, new AutoReadOnlyTxProcessingEnv(transactionProcessor, stateProvider, Substitute.For())); + MasternodeVotingContract masterVoting = new(stateProvider, new AbiEncoder(), codeSource, new AutoReadOnlyTxProcessingEnv(transactionProcessor, stateProvider, Substitute.For())); Address[] candidates = masterVoting.GetCandidates(genesis); candidates.Length.Should().Be(3); From 7864c1b3b9712489139002292be0abbeb57b02e1 Mon Sep 17 00:00:00 2001 From: ak88 Date: Fri, 21 Nov 2025 18:19:38 +0100 Subject: [PATCH 12/25] remove var --- .../Contracts/MasternodeVotingContract.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs index 52a91017c1a..11faba8b46d 100644 --- a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs +++ b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs @@ -32,14 +32,14 @@ public MasternodeVotingContract( private static AbiDefinition CreateAbiDefinition() { - var abiDefinitionParser = new AbiDefinitionParser(); + AbiDefinitionParser abiDefinitionParser = new AbiDefinitionParser(); return abiDefinitionParser.Parse(typeof(MasternodeVotingContract)); } public UInt256 GetCandidateStake(BlockHeader blockHeader, Address candidate) { - var callInfo = new CallInfo(blockHeader, "getCandidateCap", Address.SystemUser, candidate); - var result = this._constant.Call(callInfo); + CallInfo callInfo = new CallInfo(blockHeader, "getCandidateCap", Address.SystemUser, candidate); + object[] result = _constant.Call(callInfo); if (result.Length != 1) throw new InvalidOperationException("Expected 'getCandidateCap' to return exactly one result."); @@ -48,8 +48,8 @@ public UInt256 GetCandidateStake(BlockHeader blockHeader, Address candidate) public Address[] GetCandidates(BlockHeader blockHeader) { - var callInfo = new CallInfo(blockHeader, "getCandidates", Address.SystemUser); - var result = this._constant.Call(callInfo); + CallInfo callInfo = new CallInfo(blockHeader, "getCandidates", Address.SystemUser); + object[] result = _constant.Call(callInfo); return (Address[])result[0]!; } @@ -60,16 +60,16 @@ public Address[] GetCandidates(BlockHeader blockHeader) /// public Address[] GetCandidatesFromState(BlockHeader header) { - var variableSlot = CandidateContractSlots.Candidates; + CandidateContractSlots variableSlot = CandidateContractSlots.Candidates; Span input = [(byte)variableSlot]; var slot = new UInt256(Keccak.Compute(input).Bytes); - using var state = _worldState.BeginScope(header); + using IDisposable state = _worldState.BeginScope(header); ReadOnlySpan storageCell = _worldState.Get(new StorageCell(ContractAddress, slot)); - var length = new UInt256(storageCell); + UInt256 length = new UInt256(storageCell); Address[] candidates = new Address[(ulong)length]; for (int i = 0; i < length; i++) { - var key = CalculateArrayKey(slot, (ulong)i, 1); + UInt256 key = CalculateArrayKey(slot, (ulong)i, 1); candidates[i] = new Address(_worldState.Get(new StorageCell(ContractAddress, key))); } return candidates; From 5b1fc8f35a6264cff3098f0b8c476a32eafd932d Mon Sep 17 00:00:00 2001 From: ak88 Date: Mon, 24 Nov 2025 11:32:17 +0100 Subject: [PATCH 13/25] format --- .../Contracts/MasternodeVotingContractTests.cs | 1 + src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcAbiLoadTests.cs | 1 + .../Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs | 1 + .../Nethermind.Xdc/Contracts/MasternodeVotingContract.cs | 1 + src/Nethermind/Nethermind.Xdc/Contracts/XdcContractData.cs | 1 + 5 files changed, 5 insertions(+) diff --git a/src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs b/src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs index 4c86dade68b..611ac1d2482 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs @@ -29,6 +29,7 @@ using static Nethermind.Consensus.Processing.AutoReadOnlyTxProcessingEnvFactory; namespace Nethermind.Xdc.Test; + internal class MasternodeVotingContractTests { [Test] diff --git a/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcAbiLoadTests.cs b/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcAbiLoadTests.cs index a8e7398e45c..8190abbeb53 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcAbiLoadTests.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/Contracts/XdcAbiLoadTests.cs @@ -9,6 +9,7 @@ using System; namespace Nethermind.Xdc.Test.Contracts; + internal class XdcAbiLoadTests { [TestCase(typeof(MasternodeVotingContract))] diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs b/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs index 8daadf8cb6e..bb1945b2780 100644 --- a/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs +++ b/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs @@ -5,6 +5,7 @@ using Nethermind.Int256; namespace Nethermind.Xdc.Contracts; + internal interface IMasternodeVotingContract { Address[] GetCandidates(BlockHeader blockHeader); diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs index 11faba8b46d..2f6aee1e80f 100644 --- a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs +++ b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs @@ -14,6 +14,7 @@ using System; namespace Nethermind.Xdc.Contracts; + internal class MasternodeVotingContract : Contract, IMasternodeVotingContract { private readonly IWorldState _worldState; diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/XdcContractData.cs b/src/Nethermind/Nethermind.Xdc/Contracts/XdcContractData.cs index 25938379f9b..a2bc191ccb5 100644 --- a/src/Nethermind/Nethermind.Xdc/Contracts/XdcContractData.cs +++ b/src/Nethermind/Nethermind.Xdc/Contracts/XdcContractData.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; namespace Nethermind.Xdc.Contracts; + internal static class XdcContractData { // XDCValidatorBin is the compiled bytecode used for deploying new contracts. From 23a7c127362693eea09ab114fe3875d2f9595b9a Mon Sep 17 00:00:00 2001 From: ak88 Date: Mon, 24 Nov 2025 11:36:11 +0100 Subject: [PATCH 14/25] review comments --- .../Contracts/MasternodeVotingContractTests.cs | 8 +++----- .../Nethermind.Xdc/Contracts/MasternodeVotingContract.cs | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs b/src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs index 611ac1d2482..23c2095a6a7 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/Contracts/MasternodeVotingContractTests.cs @@ -52,7 +52,7 @@ public void GetCandidatesAndStake_GenesisSetup_CanReadExpectedCandidates() stateProvider.CreateAccountIfNotExists(codeSource, 0); stateProvider.InsertCode(codeSource, ValueKeccak.Compute(code), code, Shanghai.Instance); - Dictionary storage = GenesisAllocation(); + Dictionary storage = GenesisAllocation; foreach (KeyValuePair kvp in storage) { StorageCell cell = new(codeSource, UInt256.Parse(kvp.Key)); @@ -81,9 +81,8 @@ public void GetCandidatesAndStake_GenesisSetup_CanReadExpectedCandidates() } } - private Dictionary GenesisAllocation() - { - return new Dictionary + private static Dictionary GenesisAllocation = + new Dictionary { ["0x0000000000000000000000000000000000000000000000000000000000000007"] = "0x0000000000000000000000000000000000000000000000000000000000000001", ["0x0000000000000000000000000000000000000000000000000000000000000008"] = "0x0000000000000000000000000000000000000000000000000000000000000003", @@ -118,5 +117,4 @@ private Dictionary GenesisAllocation() ["0xf4dd36495f675c407ac8f8d6dd8cc40162c854dba3ce4ce8919af34d0b1ed47c"] = "0x000000000000000000000001381047523972c9fdc3aa343e0b96900a8e2fa765", ["0xf4dd36495f675c407ac8f8d6dd8cc40162c854dba3ce4ce8919af34d0b1ed47d"] = "0x000000000000000000000000000000000000000000084595161401484a000000" }; - } } diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs index 2f6aee1e80f..8d3f7e6038f 100644 --- a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs +++ b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs @@ -76,7 +76,7 @@ public Address[] GetCandidatesFromState(BlockHeader header) return candidates; } - private UInt256 CalculateArrayKey(UInt256 slot, ulong index, ulong size) + private static UInt256 CalculateArrayKey(UInt256 slot, ulong index, ulong size) { return slot + new UInt256(index * size); } From e847dfd7723e0f229740fe9c843738c991d62fa2 Mon Sep 17 00:00:00 2001 From: cicr99 Date: Mon, 24 Nov 2025 21:22:35 +0100 Subject: [PATCH 15/25] implement calculate rewards base flow and get signing txs --- .../Spec/XdcChainSpecBasedSpecProvider.cs | 2 + .../Nethermind.Xdc/Spec/XdcReleaseSpec.cs | 4 + .../Nethermind.Xdc/XdcRewardCalculator.cs | 307 +++++++----------- 3 files changed, 121 insertions(+), 192 deletions(-) diff --git a/src/Nethermind/Nethermind.Xdc/Spec/XdcChainSpecBasedSpecProvider.cs b/src/Nethermind/Nethermind.Xdc/Spec/XdcChainSpecBasedSpecProvider.cs index bf343c85384..a6038f2f3c9 100644 --- a/src/Nethermind/Nethermind.Xdc/Spec/XdcChainSpecBasedSpecProvider.cs +++ b/src/Nethermind/Nethermind.Xdc/Spec/XdcChainSpecBasedSpecProvider.cs @@ -22,6 +22,8 @@ protected override ReleaseSpec CreateReleaseSpec(ChainSpec chainSpec, long relea releaseSpec.SwitchEpoch = chainSpecEngineParameters.SwitchEpoch; releaseSpec.SwitchBlock = chainSpecEngineParameters.SwitchBlock; releaseSpec.V2Configs = chainSpecEngineParameters.V2Configs; + releaseSpec.FoundationWallet = chainSpecEngineParameters.FoundationWalletAddr; + releaseSpec.Reward = chainSpecEngineParameters.Reward; releaseSpec.ApplyV2Config(0); diff --git a/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs b/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs index 0b8f3a4dc0d..71c0f61c52d 100644 --- a/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs @@ -11,6 +11,7 @@ public class XdcReleaseSpec : ReleaseSpec, IXdcReleaseSpec { public int EpochLength { get; set; } public int Gap { get; set; } + public long Reward { get; set; } public int SwitchEpoch { get; set; } public long SwitchBlock { get; set; } public int MaxMasternodes { get; set; } // v2 max masternodes @@ -31,6 +32,7 @@ public class XdcReleaseSpec : ReleaseSpec, IXdcReleaseSpec public Address[] GenesisMasterNodes { get; set; } public Address FoundationWallet { get; set; } + public Address BlockSignerContract { get; set; } public void ApplyV2Config(ulong round) { @@ -79,6 +81,7 @@ public interface IXdcReleaseSpec : IReleaseSpec { public int EpochLength { get; } public int Gap { get; } + public long Reward { get; } public int SwitchEpoch { get; set; } public long SwitchBlock { get; set; } public int MaxMasternodes { get; set; } // v2 max masternodes @@ -98,6 +101,7 @@ public interface IXdcReleaseSpec : IReleaseSpec public List V2Configs { get; set; } Address[] GenesisMasterNodes { get; set; } Address FoundationWallet { get; set; } + public Address BlockSignerContract { get; set; } public void ApplyV2Config(ulong round); } diff --git a/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs b/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs index ea1621efeb9..f449c7d9133 100644 --- a/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs +++ b/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs @@ -1,8 +1,10 @@ // SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Blockchain; using Nethermind.Consensus.Rewards; using Nethermind.Core; +using Nethermind.Core.Caching; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Int256; @@ -11,7 +13,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Numerics; namespace Nethermind.Xdc { @@ -24,19 +25,20 @@ namespace Nethermind.Xdc public class XdcRewardCalculator( IEpochSwitchManager epochSwitchManager, ISpecProvider specProvider, - ILogManager logManager, - IXdcSignatureTracker signatureTracker, - IXdcStakingManager stakingManager) : IRewardCalculator + IBlockTree blockTree) : IRewardCalculator { private readonly ILogger logger = logManager?.GetClassLogger() ?? NullLogger.Instance; + private LruCache _signingTxsCache = new LruCache(9000, "XDC Signing Txs Cache"); // Reward amount per epoch (5000 XDC in Wei) // 1 XDC = 10^18 Wei, so 5000 XDC = 5000 * 10^18 Wei private static readonly UInt256 EPOCH_REWARD = UInt256.Parse("5000000000000000000000"); + private const long BlocksPerYear = 15768000; + private const long MergeSignRange = 15; /// /// Calculates block rewards according to XDPoS consensus rules. - /// + /// /// For XDPoS, rewards are only distributed at epoch checkpoints (blocks where number % 900 == 0). /// At these checkpoints, rewards are calculated based on masternode signature counts during /// the previous epoch and distributed according to the 40/50/10 split model. @@ -50,92 +52,41 @@ public BlockReward[] CalculateRewards(Block block) if (block.Header is not XdcBlockHeader xdcHeader) throw new InvalidOperationException("Only supports XDC headers"); + var rewards = new List(); + var number = xdcHeader.Number; IXdcReleaseSpec spec = specProvider.GetXdcSpec(xdcHeader, xdcHeader.ExtraConsensusData.BlockRound); + if(number == spec.SwitchBlock + 1) return rewards.ToArray(); - if (!epochSwitchManager.IsEpochSwitchAtBlock(xdcHeader)) - { - // Non-checkpoint blocks don't trigger reward distribution in XDPoS - // The block producer still gets transaction fees, but no block reward - if (logger.IsTrace) logger.Trace($"Block {block.Number} is not an epoch switch, no rewards distributed"); - return Array.Empty(); - } - - // Calculate the epoch that just completed - long completedEpoch = (block.Number / spec.EpochLength) - 1; - long epochStartBlock = completedEpoch * spec.EpochLength + 1; - long epochEndBlock = (completedEpoch + 1) * spec.EpochLength; - - var epochNumber = spec.SwitchEpoch + (long)xdcHeader.ExtraConsensusData.BlockRound / spec.EpochLength; - - var originReward = spec.BlockReward * Unit.Ether; - try - { - // Get signature counts for all masternodes in the completed epoch - var signatureCounts = signatureTracker.GetSignatureCounts(epochStartBlock, epochEndBlock); - - if (signatureCounts == null || signatureCounts.Count == 0) - { - logger.Warn($"No signature data available for epoch {completedEpoch}"); - return Array.Empty(); - } - - // Calculate total signatures across all masternodes - long totalSignatures = signatureCounts.Values.Sum(); - - if (totalSignatures == 0) - { - logger.Warn($"Total signatures for epoch {completedEpoch} is zero"); - return Array.Empty(); - } - - // Calculate and distribute rewards - var rewards = new List(); - - foreach (var masternodeSignature in signatureCounts) - { - Address masternodeAddress = masternodeSignature.Key; - long signatureCount = masternodeSignature.Value; - - // Calculate this masternode's proportional share of the epoch reward - // Formula: (masternode_signatures / total_signatures) * EPOCH_REWARD - UInt256 masternodeBaseReward = CalculateProportionalReward( - signatureCount, - totalSignatures, - EPOCH_REWARD - ); - - // Split the reward according to XDPoS distribution model - var (infraReward, stakingPool, foundationReward) = SplitReward(masternodeBaseReward); + var foundationWalletAddr = spec.FoundationWallet; + if (foundationWalletAddr == Address.Zero) throw new InvalidOperationException("Foundation wallet address cannot be empty"); - // 1. Infrastructure reward (40%) goes directly to masternode operator - rewards.Add(new BlockReward(masternodeAddress, infraReward, BlockRewardType.Block)); + var round = xdcHeader.ExtraConsensusData.BlockRound; + var epochNumber = spec.SwitchEpoch + (int) round / spec.EpochLength; - // 2. Foundation reward (10%) goes to XDC Foundation - rewards.Add(new BlockReward(spec.FoundationWallet, foundationReward, BlockRewardType.External)); + var signers = GetSigningTxCount(number, xdcHeader, spec); - // 3. Staking reward (50%) is distributed among delegators proportionally - var delegatorRewards = DistributeStakingRewards( - masternodeAddress, - stakingPool, - block.Number - ); + //TODO: Check TIPUpdateReward behavior, it appears to be set to infinite for mainnet + // The following code is only for when IsTIPUpgradeReward(header.Number) is false + var originalReward = (UInt256)spec.Reward * Unit.Ether; + var chainReward = RewardInflation(spec, originalReward, number); + Dictionary rewardSigners = CalculateRewardForSigners(chainReward, signers); - rewards.AddRange(delegatorRewards); - } - - return rewards.ToArray(); - } - catch (Exception ex) + UInt256 totalFoundationWalletReward = UInt256.Zero; + foreach (var (signer, reward) in rewardSigners) { - logger.Error($"Error calculating XDPoS rewards for block {block.Number}", ex); - throw; + (BlockReward holderReward, UInt256 foundationWalletReward) = CalculateRewardForHolders(); + //TODO: stateBlock.AddBalance(holderReward) + totalFoundationWalletReward += foundationWalletReward; + rewards.Add(holderReward); } + rewards.Add(new BlockReward(foundationWalletAddr, totalFoundationWalletReward)); + return rewards.ToArray(); } /// /// Calculates a proportional reward based on the number of signatures. /// Uses UInt256 arithmetic to maintain precision with large Wei values. - /// + /// /// Formula: (signatureCount / totalSignatures) * totalReward /// private UInt256 CalculateProportionalReward( @@ -160,149 +111,121 @@ private UInt256 CalculateProportionalReward( return reward; } - /// - /// Splits a masternode's base reward according to the XDPoS distribution model: - /// - 40% Infrastructure (masternode operator) - /// - 50% Staking (delegators) - /// - 10% Foundation (XDC Foundation) - /// - private (UInt256 infrastructure, UInt256 staking, UInt256 foundation) SplitReward(UInt256 baseReward) - { - // Calculate each component - // Using integer division with appropriate scaling to avoid precision loss - - // 40% for infrastructure - UInt256 infrastructure = (baseReward * 40) / 100; - - // 50% for staking pool - UInt256 staking = (baseReward * 50) / 100; - - // 10% for foundation - UInt256 foundation = (baseReward * 10) / 100; - - // Handle any rounding remainder by adding it to infrastructure - UInt256 allocated = infrastructure + staking + foundation; - if (allocated < baseReward) - { - infrastructure += (baseReward - allocated); - } - - return (infrastructure, staking, foundation); - } - - /// - /// Distributes the staking reward pool among all delegators who have staked with this masternode. - /// Each delegator receives a proportion based on their stake amount relative to the total stake. - /// - /// Only delegators who were active at the checkpoint block receive rewards. - /// - private List DistributeStakingRewards( - Address masternodeAddress, - UInt256 stakingPool, - long checkpointBlock) + public Dictionary GetSigningTxCount(long number, XdcBlockHeader header, IXdcReleaseSpec spec) { - var delegatorRewards = new List(); - - if (stakingPool.IsZero) - { - return delegatorRewards; - } - - // Get all active stakes for this masternode at the checkpoint - var stakes = stakingManager.GetActiveStakes(masternodeAddress, checkpointBlock); - - if (stakes == null || stakes.Count == 0) + long signEpochCount = 1, rewardEpochCount = 2, epochCount = 0, endBlockNumber = number, startBlockNumber = 0; + var signers = new Dictionary(); + var blockNumberToHash = new Dictionary(); + var hashToSigningAddress = new Dictionary>(); + var masternodes = new HashSet
(); + + if (number == 0) return signers; + var h = header; + for (long i = number - 1; i >= 0; i--) { - // No delegators, staking pool could be reallocated to infrastructure - // or left undistributed depending on implementation choice - if (logger.IsDebug) + h = blockTree.FindHeader(h.ParentHash, i) as XdcBlockHeader; + if (h == null) throw new InvalidOperationException($"Header with hash {h.ParentHash} not found"); + if (epochSwitchManager.IsEpochSwitchAtBlock(h) && i != spec.SwitchBlock + 1) { - logger.Debug($"No active delegators for masternode {masternodeAddress}, staking pool: {stakingPool} Wei"); + epochCount++; + if (epochCount == signEpochCount) endBlockNumber = i; + if (epochCount == rewardEpochCount) + { + startBlockNumber = i + 1; + // Get masternodes from epoch switch header + masternodes = new HashSet
(h.ValidatorsAddress!); + // Ignore behavior for IsTIPUpgradeReward which calculates protectors and observers + break; + } } - return delegatorRewards; - } - // Calculate total stake across all delegators - UInt256 totalStake = UInt256.Zero; - foreach (var stake in stakes) - { - totalStake += stake.Amount; - } + blockNumberToHash[i] = h.Hash; + if (!_signingTxsCache.TryGet(h.Hash, out Transaction[] signingTxs)) + { + var block = blockTree.FindBlock(i); + if (block == null) throw new InvalidOperationException($"Block with hash {h.Hash} not found"); + var txs = block.Transactions; + signingTxs = CacheSigningTxs(h.Hash!, txs, spec); + } - if (totalStake.IsZero) - { - logger.Warn($"Total stake is zero for masternode {masternodeAddress}"); - return delegatorRewards; + foreach (var tx in signingTxs) + { + Hash256 blockHash = ExtractBlockHashFromSigningTxData(tx.Data); + if (!hashToSigningAddress.ContainsKey(blockHash)) + hashToSigningAddress[blockHash] = new List
(); + hashToSigningAddress[blockHash].Add(tx.SenderAddress); + } } - // Distribute rewards proportionally to each delegator - foreach (var stake in stakes) + // Only blocks every MergeSignRange are used to gather signing txs? Or is it that already signing txs are done every MergeSignRange amount of blocks? + // Calculate start >= startBlockNumber so that start % MergeSignRange == 0 + long start = ((startBlockNumber + MergeSignRange - 1) / MergeSignRange) * MergeSignRange; + for (long i = start; i < endBlockNumber; i += MergeSignRange) { - // Formula: (delegator_stake / total_stake) * staking_pool - UInt256 delegatorReward = (stake.Amount * stakingPool) / totalStake; - - if (!delegatorReward.IsZero) + var addrs = hashToSigningAddress[blockNumberToHash[i]]; + foreach (var addr in addrs) { - delegatorRewards.Add(new BlockReward( - stake.DelegatorAddress, - delegatorReward, - BlockRewardType.External - )); + if (!masternodes.Contains(addr)) continue; + if (!signers.ContainsKey(addr)) signers[addr] = 0; + signers[addr] += 1; } } - - return delegatorRewards; + return signers; } - public UInt256 RewardInflation(IXdcReleaseSpec spec, UInt256 chainReward, long number, long blockPerYear) + public UInt256 RewardInflation(IXdcReleaseSpec spec, UInt256 chainReward, long number) { + //TODO: If IsTIPNoHalvingMNReward(blockNumber) is true we should return chainReward immediately UInt256 reward = chainReward; - if (blockPerYear * 2 <= number && number < blockPerYear * 5) + if (BlocksPerYear * 2 <= number && number < BlocksPerYear * 5) { reward = chainReward / 2; } - if (blockPerYear * 5 <= number) + if (BlocksPerYear * 5 <= number) { reward = chainReward / 4; } return reward; } - } - public class StakePosition - { - public Address DelegatorAddress { get; set; } - public UInt256 Amount { get; set; } - public long StakedAtBlock { get; set; } + private Transaction[] CacheSigningTxs(Hash256 hash, Transaction[] txs, IXdcReleaseSpec spec) + { + var signingTxs = txs.Where(t => IsSigningTransaction(t, spec)).ToArray(); + _signingTxsCache.Set(hash, signingTxs); + return signingTxs; + } - public StakePosition(Address delegator, UInt256 amount, long stakedAt) + private bool IsSigningTransaction(Transaction tx, IXdcReleaseSpec spec) { - DelegatorAddress = delegator; - Amount = amount; - StakedAtBlock = stakedAt; + if (tx.To is null || tx.To != spec.BlockSignerContract) return false; + + // Check data corresponds to Signing transaction: + // function sign(uint256 _blockNumber, bytes32 _blockHash) + if (tx.Data.Length != 32 * 2 + 4) return false; + + return ExtractSelectorFromSigningTxData(tx.Data) == "0xe341eaa4"; } - } - public interface IXdcSignatureTracker - { - /// - /// Gets the signature count for each masternode between the specified block range. - /// - /// Start of the range (inclusive) - /// End of the range (inclusive) - /// Dictionary mapping masternode address to signature count - Dictionary GetSignatureCounts(long startBlock, long endBlock); - } + private String ExtractSelectorFromSigningTxData(ReadOnlyMemory data) + { + var span = data.Span; + if (span.Length == 68) + throw new ArgumentException("Signing tx calldata must be exactly 68 bytes (4 + 32 + 32).", nameof(data)); - public interface IXdcStakingManager - { - /// - /// Gets all active stake positions for a masternode at a specific block. - /// Only returns stakes that were active (not withdrawn) at the checkpoint. - /// - /// The masternode address - /// The block number to check stakes at - /// List of active stake positions - List GetActiveStakes(Address masternodeAddress, long atBlock); + // 0..3: selector + var selBytes = span.Slice(0, 4); + return "0x" + Convert.ToHexString(selBytes).ToLowerInvariant(); + } + + private Hash256 ExtractBlockHashFromSigningTxData(ReadOnlyMemory data) + { + var span = data.Span; + if (span.Length == 68) + throw new ArgumentException("Signing tx calldata must be exactly 68 bytes (4 + 32 + 32).", nameof(data)); + + // 36..67: bytes32 blockHash + var hashBytes = span.Slice(36, 32); + return new Hash256(hashBytes); + } } } From fe9df29d6ef75a02bb45184af2ff6a1a0a3ea840 Mon Sep 17 00:00:00 2001 From: cicr99 Date: Mon, 24 Nov 2025 21:53:43 +0100 Subject: [PATCH 16/25] implement rewards per signer and distribution calculations --- .../Nethermind.Xdc/XdcRewardCalculator.cs | 113 +++++++++++------- 1 file changed, 71 insertions(+), 42 deletions(-) diff --git a/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs b/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs index f449c7d9133..758dc4722fa 100644 --- a/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs +++ b/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs @@ -8,7 +8,6 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Int256; -using Nethermind.Logging; using Nethermind.Xdc.Spec; using System; using System.Collections.Generic; @@ -19,7 +18,7 @@ namespace Nethermind.Xdc /// /// Rewards are distributed at epoch boundaries (every 900 blocks) based on: /// - Masternode signature count during the epoch - /// - 40% infrastructure / 50% staking / 10% foundation split + /// - 90% masternode / 10% foundation split /// - Proportional distribution among delegators based on stake /// public class XdcRewardCalculator( @@ -27,12 +26,8 @@ public class XdcRewardCalculator( ISpecProvider specProvider, IBlockTree blockTree) : IRewardCalculator { - private readonly ILogger logger = logManager?.GetClassLogger() ?? NullLogger.Instance; - private LruCache _signingTxsCache = new LruCache(9000, "XDC Signing Txs Cache"); - // Reward amount per epoch (5000 XDC in Wei) - // 1 XDC = 10^18 Wei, so 5000 XDC = 5000 * 10^18 Wei - private static readonly UInt256 EPOCH_REWARD = UInt256.Parse("5000000000000000000000"); + private LruCache _signingTxsCache = new(9000, "XDC Signing Txs Cache"); private const long BlocksPerYear = 15768000; private const long MergeSignRange = 15; @@ -63,18 +58,18 @@ public BlockReward[] CalculateRewards(Block block) var round = xdcHeader.ExtraConsensusData.BlockRound; var epochNumber = spec.SwitchEpoch + (int) round / spec.EpochLength; - var signers = GetSigningTxCount(number, xdcHeader, spec); + var (signers, count) = GetSigningTxCount(number, xdcHeader, spec); //TODO: Check TIPUpdateReward behavior, it appears to be set to infinite for mainnet // The following code is only for when IsTIPUpgradeReward(header.Number) is false var originalReward = (UInt256)spec.Reward * Unit.Ether; var chainReward = RewardInflation(spec, originalReward, number); - Dictionary rewardSigners = CalculateRewardForSigners(chainReward, signers); + Dictionary rewardSigners = CalculateRewardForSigners(chainReward, signers, count); UInt256 totalFoundationWalletReward = UInt256.Zero; foreach (var (signer, reward) in rewardSigners) { - (BlockReward holderReward, UInt256 foundationWalletReward) = CalculateRewardForHolders(); + (BlockReward holderReward, UInt256 foundationWalletReward) = DistributeRewards(spec.FoundationWallet, signer, reward); //TODO: stateBlock.AddBalance(holderReward) totalFoundationWalletReward += foundationWalletReward; rewards.Add(holderReward); @@ -83,43 +78,15 @@ public BlockReward[] CalculateRewards(Block block) return rewards.ToArray(); } - /// - /// Calculates a proportional reward based on the number of signatures. - /// Uses UInt256 arithmetic to maintain precision with large Wei values. - /// - /// Formula: (signatureCount / totalSignatures) * totalReward - /// - private UInt256 CalculateProportionalReward( - long signatureCount, - long totalSignatures, - UInt256 totalReward) + public (Dictionary Signers, long Count) GetSigningTxCount(long number, XdcBlockHeader header, IXdcReleaseSpec spec) { - if (signatureCount <= 0 || totalSignatures <= 0) - { - return UInt256.Zero; - } - - // Convert to UInt256 for precision - UInt256 signatures = (UInt256)signatureCount; - UInt256 total = (UInt256)totalSignatures; - - // Calculate: (signatures * totalReward) / total - // Order of operations matters to maintain precision - UInt256 numerator = signatures * totalReward; - UInt256 reward = numerator / total; - - return reward; - } - - public Dictionary GetSigningTxCount(long number, XdcBlockHeader header, IXdcReleaseSpec spec) - { - long signEpochCount = 1, rewardEpochCount = 2, epochCount = 0, endBlockNumber = number, startBlockNumber = 0; + long signEpochCount = 1, rewardEpochCount = 2, epochCount = 0, endBlockNumber = number, startBlockNumber = 0, signingCount = 0; var signers = new Dictionary(); var blockNumberToHash = new Dictionary(); var hashToSigningAddress = new Dictionary>(); var masternodes = new HashSet
(); - if (number == 0) return signers; + if (number == 0) return (signers, signingCount); var h = header; for (long i = number - 1; i >= 0; i--) { @@ -168,9 +135,10 @@ public Dictionary GetSigningTxCount(long number, XdcBlockHeader h if (!masternodes.Contains(addr)) continue; if (!signers.ContainsKey(addr)) signers[addr] = 0; signers[addr] += 1; + signingCount++; } } - return signers; + return (signers, signingCount); } public UInt256 RewardInflation(IXdcReleaseSpec spec, UInt256 chainReward, long number) @@ -227,5 +195,66 @@ private Hash256 ExtractBlockHashFromSigningTxData(ReadOnlyMemory data) var hashBytes = span.Slice(36, 32); return new Hash256(hashBytes); } + + private Dictionary CalculateRewardForSigners(UInt256 totalReward, + Dictionary signers, long totalSigningCount) + { + var rewardSigners = new Dictionary(); + foreach (var (signer, count) in signers) + { + UInt256 reward = CalculateProportionalReward(count, totalSigningCount, totalReward); + rewardSigners.Add(signer, reward); + } + return rewardSigners; + } + + /// + /// Calculates a proportional reward based on the number of signatures. + /// Uses UInt256 arithmetic to maintain precision with large Wei values. + /// + /// Formula: (signatureCount / totalSignatures) * totalReward + /// + private UInt256 CalculateProportionalReward( + long signatureCount, + long totalSignatures, + UInt256 totalReward) + { + if (signatureCount <= 0 || totalSignatures <= 0) + { + return UInt256.Zero; + } + + // Convert to UInt256 for precision + UInt256 signatures = (UInt256)signatureCount; + UInt256 total = (UInt256)totalSignatures; + + // Calculate: (signatures * totalReward) / total + // Order of operations matters to maintain precision + UInt256 numerator = signatures * totalReward; + UInt256 reward = numerator / total; + + return reward; + } + + private (BlockReward HolderReward, UInt256 FoundationWalletReward) DistributeRewards( + Address foundationWalletAddress, Address masternodeAddress, UInt256 reward) + { + Address owner = GetCandidatesOwnerBySigner(masternodeAddress); + + // 90% of the reward goes to the masternode + UInt256 masterReward = reward * 90 / 100; + + // 10% of the reward goes to the foundation wallet + UInt256 foundationReward = reward / 10; + + //TODO: Is it possible owner address is the same as foundation wallet address? + return (new BlockReward(owner, masterReward), foundationReward); + } + + private Address GetCandidatesOwnerBySigner(Address signerAddress) + { + // Use state to get candidate + return signerAddress; + } } } From 3536869200ef334113fb8bfbf83a3ce7147daf83 Mon Sep 17 00:00:00 2001 From: cicr99 Date: Tue, 25 Nov 2025 17:10:38 +0100 Subject: [PATCH 17/25] implement getCadidateOwner --- .../Contracts/IMasternodeVotingContract.cs | 3 ++- .../Contracts/MasternodeVotingContract.cs | 12 +++++++++++- .../Nethermind.Xdc/XdcRewardCalculator.cs | 16 ++++++---------- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs b/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs index bb1945b2780..520f16b8db7 100644 --- a/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs +++ b/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs @@ -6,8 +6,9 @@ namespace Nethermind.Xdc.Contracts; -internal interface IMasternodeVotingContract +public interface IMasternodeVotingContract { Address[] GetCandidates(BlockHeader blockHeader); UInt256 GetCandidateStake(BlockHeader blockHeader, Address candidate); + Address GetCandidateOwner(BlockHeader blockHeader, Address candidate); } diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs index 8d3f7e6038f..47f359bd840 100644 --- a/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs +++ b/src/Nethermind/Nethermind.Xdc/Contracts/MasternodeVotingContract.cs @@ -15,7 +15,7 @@ namespace Nethermind.Xdc.Contracts; -internal class MasternodeVotingContract : Contract, IMasternodeVotingContract +public class MasternodeVotingContract : Contract, IMasternodeVotingContract { private readonly IWorldState _worldState; private IConstantContract _constant; @@ -47,6 +47,16 @@ public UInt256 GetCandidateStake(BlockHeader blockHeader, Address candidate) return (UInt256)result[0]!; } + public Address GetCandidateOwner(BlockHeader blockHeader, Address candidate) + { + CallInfo callInfo = new CallInfo(blockHeader, "getCandidateOwner", Address.SystemUser, candidate); + object[] result = _constant.Call(callInfo); + if (result.Length != 1) + throw new InvalidOperationException("Expected 'getCandidateOwner' to return exactly one result."); + + return (Address)result[0]!; + } + public Address[] GetCandidates(BlockHeader blockHeader) { CallInfo callInfo = new CallInfo(blockHeader, "getCandidates", Address.SystemUser); diff --git a/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs b/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs index 758dc4722fa..0f7e9925d85 100644 --- a/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs +++ b/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Nethermind.Xdc.Contracts; namespace Nethermind.Xdc { @@ -24,7 +25,8 @@ namespace Nethermind.Xdc public class XdcRewardCalculator( IEpochSwitchManager epochSwitchManager, ISpecProvider specProvider, - IBlockTree blockTree) : IRewardCalculator + IBlockTree blockTree, + IMasternodeVotingContract masternodeVotingContract) : IRewardCalculator { private LruCache _signingTxsCache = new(9000, "XDC Signing Txs Cache"); @@ -69,7 +71,7 @@ public BlockReward[] CalculateRewards(Block block) UInt256 totalFoundationWalletReward = UInt256.Zero; foreach (var (signer, reward) in rewardSigners) { - (BlockReward holderReward, UInt256 foundationWalletReward) = DistributeRewards(spec.FoundationWallet, signer, reward); + (BlockReward holderReward, UInt256 foundationWalletReward) = DistributeRewards(signer, reward, xdcHeader); //TODO: stateBlock.AddBalance(holderReward) totalFoundationWalletReward += foundationWalletReward; rewards.Add(holderReward); @@ -237,9 +239,9 @@ private UInt256 CalculateProportionalReward( } private (BlockReward HolderReward, UInt256 FoundationWalletReward) DistributeRewards( - Address foundationWalletAddress, Address masternodeAddress, UInt256 reward) + Address masternodeAddress, UInt256 reward, XdcBlockHeader header) { - Address owner = GetCandidatesOwnerBySigner(masternodeAddress); + Address owner = masternodeVotingContract.GetCandidateOwner(header, masternodeAddress); // 90% of the reward goes to the masternode UInt256 masterReward = reward * 90 / 100; @@ -250,11 +252,5 @@ private UInt256 CalculateProportionalReward( //TODO: Is it possible owner address is the same as foundation wallet address? return (new BlockReward(owner, masterReward), foundationReward); } - - private Address GetCandidatesOwnerBySigner(Address signerAddress) - { - // Use state to get candidate - return signerAddress; - } } } From a350bcd75546fba4fcbb13456ab7cd14afc42cad Mon Sep 17 00:00:00 2001 From: cicr99 Date: Tue, 25 Nov 2025 18:52:26 +0100 Subject: [PATCH 18/25] refactors and add comments to the code --- .../Nethermind.Xdc/XdcRewardCalculator.cs | 69 ++++++++----------- 1 file changed, 27 insertions(+), 42 deletions(-) diff --git a/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs b/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs index 0f7e9925d85..e1f2fefc54b 100644 --- a/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs +++ b/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs @@ -17,10 +17,12 @@ namespace Nethermind.Xdc { /// - /// Rewards are distributed at epoch boundaries (every 900 blocks) based on: - /// - Masternode signature count during the epoch - /// - 90% masternode / 10% foundation split - /// - Proportional distribution among delegators based on stake + /// Reward model (current mainnet): + /// - Rewards are paid only at epoch checkpoints (number % EpochLength == 0). + /// - For now we **ignore** TIPUpgradeReward behavior because on mainnet + /// the upgrade activation is set far in the future (effectively “not active”). + /// When TIPUpgradeReward activates, protector/observer beneficiaries must be added. + /// - Current split implemented here: 90% to masternode owner, 10% to foundation. /// public class XdcRewardCalculator( IEpochSwitchManager epochSwitchManager, @@ -28,9 +30,10 @@ public class XdcRewardCalculator( IBlockTree blockTree, IMasternodeVotingContract masternodeVotingContract) : IRewardCalculator { - private LruCache _signingTxsCache = new(9000, "XDC Signing Txs Cache"); private const long BlocksPerYear = 15768000; + // XDC rule: signing transactions are sampled/merged every N blocks (N=15 on XDC). + // Only block numbers that are multiples of MergeSignRange are considered when tallying signers. private const long MergeSignRange = 15; /// @@ -38,7 +41,7 @@ public class XdcRewardCalculator( /// /// For XDPoS, rewards are only distributed at epoch checkpoints (blocks where number % 900 == 0). /// At these checkpoints, rewards are calculated based on masternode signature counts during - /// the previous epoch and distributed according to the 40/50/10 split model. + /// the previous epoch and distributed according to the 90/10 split model. /// /// The block to calculate rewards for /// Array of BlockReward objects for all reward recipients @@ -57,15 +60,9 @@ public BlockReward[] CalculateRewards(Block block) var foundationWalletAddr = spec.FoundationWallet; if (foundationWalletAddr == Address.Zero) throw new InvalidOperationException("Foundation wallet address cannot be empty"); - var round = xdcHeader.ExtraConsensusData.BlockRound; - var epochNumber = spec.SwitchEpoch + (int) round / spec.EpochLength; - var (signers, count) = GetSigningTxCount(number, xdcHeader, spec); - //TODO: Check TIPUpdateReward behavior, it appears to be set to infinite for mainnet - // The following code is only for when IsTIPUpgradeReward(header.Number) is false - var originalReward = (UInt256)spec.Reward * Unit.Ether; - var chainReward = RewardInflation(spec, originalReward, number); + var chainReward = (UInt256)spec.Reward * Unit.Ether; Dictionary rewardSigners = CalculateRewardForSigners(chainReward, signers, count); UInt256 totalFoundationWalletReward = UInt256.Zero; @@ -85,15 +82,16 @@ public BlockReward[] CalculateRewards(Block block) long signEpochCount = 1, rewardEpochCount = 2, epochCount = 0, endBlockNumber = number, startBlockNumber = 0, signingCount = 0; var signers = new Dictionary(); var blockNumberToHash = new Dictionary(); - var hashToSigningAddress = new Dictionary>(); + var hashToSigningAddress = new Dictionary>(); var masternodes = new HashSet
(); if (number == 0) return (signers, signingCount); var h = header; for (long i = number - 1; i >= 0; i--) { - h = blockTree.FindHeader(h.ParentHash, i) as XdcBlockHeader; - if (h == null) throw new InvalidOperationException($"Header with hash {h.ParentHash} not found"); + var parentHash = h.ParentHash; + h = blockTree.FindHeader(parentHash, i) as XdcBlockHeader; + if (h == null) throw new InvalidOperationException($"Header with hash {parentHash} not found"); if (epochSwitchManager.IsEpochSwitchAtBlock(h) && i != spec.SwitchBlock + 1) { epochCount++; @@ -103,7 +101,9 @@ public BlockReward[] CalculateRewards(Block block) startBlockNumber = i + 1; // Get masternodes from epoch switch header masternodes = new HashSet
(h.ValidatorsAddress!); - // Ignore behavior for IsTIPUpgradeReward which calculates protectors and observers + // TIPUpgradeReward path (protector/observer selection) is currently ignored, + // because on mainnet the upgrade height is set to an effectively unreachable block. + // If/when that changes, we must compute protector/observer sets here. break; } } @@ -117,22 +117,22 @@ public BlockReward[] CalculateRewards(Block block) signingTxs = CacheSigningTxs(h.Hash!, txs, spec); } - foreach (var tx in signingTxs) + foreach (Transaction tx in signingTxs) { Hash256 blockHash = ExtractBlockHashFromSigningTxData(tx.Data); if (!hashToSigningAddress.ContainsKey(blockHash)) - hashToSigningAddress[blockHash] = new List
(); + hashToSigningAddress[blockHash] = new HashSet
(); hashToSigningAddress[blockHash].Add(tx.SenderAddress); } } - // Only blocks every MergeSignRange are used to gather signing txs? Or is it that already signing txs are done every MergeSignRange amount of blocks? + // Only blocks at heights that are multiples of MergeSignRange are considered. // Calculate start >= startBlockNumber so that start % MergeSignRange == 0 long start = ((startBlockNumber + MergeSignRange - 1) / MergeSignRange) * MergeSignRange; for (long i = start; i < endBlockNumber; i += MergeSignRange) { var addrs = hashToSigningAddress[blockNumberToHash[i]]; - foreach (var addr in addrs) + foreach (Address addr in addrs) { if (!masternodes.Contains(addr)) continue; if (!signers.ContainsKey(addr)) signers[addr] = 0; @@ -143,21 +143,6 @@ public BlockReward[] CalculateRewards(Block block) return (signers, signingCount); } - public UInt256 RewardInflation(IXdcReleaseSpec spec, UInt256 chainReward, long number) - { - //TODO: If IsTIPNoHalvingMNReward(blockNumber) is true we should return chainReward immediately - UInt256 reward = chainReward; - if (BlocksPerYear * 2 <= number && number < BlocksPerYear * 5) - { - reward = chainReward / 2; - } - if (BlocksPerYear * 5 <= number) - { - reward = chainReward / 4; - } - return reward; - } - private Transaction[] CacheSigningTxs(Hash256 hash, Transaction[] txs, IXdcReleaseSpec spec) { var signingTxs = txs.Where(t => IsSigningTransaction(t, spec)).ToArray(); @@ -165,13 +150,13 @@ private Transaction[] CacheSigningTxs(Hash256 hash, Transaction[] txs, IXdcRelea return signingTxs; } + // Signing transaction ABI (Solidity): + // function sign(uint256 _blockNumber, bytes32 _blockHash) + // Calldata = 4-byte selector + 32-byte big-endian uint + 32-byte bytes32 = 68 bytes total. private bool IsSigningTransaction(Transaction tx, IXdcReleaseSpec spec) { if (tx.To is null || tx.To != spec.BlockSignerContract) return false; - - // Check data corresponds to Signing transaction: - // function sign(uint256 _blockNumber, bytes32 _blockHash) - if (tx.Data.Length != 32 * 2 + 4) return false; + if (tx.Data.Length != 68) return false; return ExtractSelectorFromSigningTxData(tx.Data) == "0xe341eaa4"; } @@ -179,7 +164,7 @@ private bool IsSigningTransaction(Transaction tx, IXdcReleaseSpec spec) private String ExtractSelectorFromSigningTxData(ReadOnlyMemory data) { var span = data.Span; - if (span.Length == 68) + if (span.Length != 68) throw new ArgumentException("Signing tx calldata must be exactly 68 bytes (4 + 32 + 32).", nameof(data)); // 0..3: selector @@ -190,7 +175,7 @@ private String ExtractSelectorFromSigningTxData(ReadOnlyMemory data) private Hash256 ExtractBlockHashFromSigningTxData(ReadOnlyMemory data) { var span = data.Span; - if (span.Length == 68) + if (span.Length != 68) throw new ArgumentException("Signing tx calldata must be exactly 68 bytes (4 + 32 + 32).", nameof(data)); // 36..67: bytes32 blockHash From 11347baa3a6a0e3cd468affb3e14412fad11b576 Mon Sep 17 00:00:00 2001 From: cicr99 Date: Wed, 26 Nov 2025 10:47:44 +0100 Subject: [PATCH 19/25] add block signer contract address to the configuration spec --- src/Nethermind/Chains/xdc.json | 3 ++- src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Chains/xdc.json b/src/Nethermind/Chains/xdc.json index d96bdac61bc..d94865903f1 100644 --- a/src/Nethermind/Chains/xdc.json +++ b/src/Nethermind/Chains/xdc.json @@ -71,7 +71,8 @@ "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "eip155Block": 3, "eip158Block": 3, - "byzantiumBlock": 4 + "byzantiumBlock": 4, + "blockSignerContract": "0x0000000000000000000000000000000000000089" }, "genesis": { "nonce": "0x0", diff --git a/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs b/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs index 27c98093c13..e66741685a7 100644 --- a/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Xdc/Spec/XdcReleaseSpec.cs @@ -103,7 +103,7 @@ public interface IXdcReleaseSpec : IReleaseSpec public List V2Configs { get; set; } Address[] GenesisMasterNodes { get; set; } Address FoundationWallet { get; set; } - public Address BlockSignerContract { get; set; } + Address BlockSignerContract { get; set; } Address MasternodeVotingContract { get; set; } public void ApplyV2Config(ulong round); From f6ea6344b2856d906bf5d81e9981e4a5aad3d7d6 Mon Sep 17 00:00:00 2001 From: cicr99 Date: Wed, 3 Dec 2025 19:26:02 +0100 Subject: [PATCH 20/25] implement reward module tests --- .../Helpers/XdcTestBlockchain.cs | 24 +- .../ModuleTests/RewardTests.cs | 249 ++++++++++++++++++ .../Nethermind.Xdc/XdcRewardCalculator.cs | 46 ++-- 3 files changed, 294 insertions(+), 25 deletions(-) create mode 100644 src/Nethermind/Nethermind.Xdc.Test/ModuleTests/RewardTests.cs diff --git a/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs b/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs index 33f5e224e9d..748926f235d 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs @@ -55,7 +55,7 @@ public static async Task Create(int blocksToAdd = 3, bool use if (testConfiguration.SuggestGenesisOnStart) { - // The block added event is not waited by genesis, but its needed to wait here so that `AddBlock` wait correctly. + // The block added event is not waited by genesis, but it's needed to wait here so that `AddBlock` waits correctly. Task newBlockWaiter = chain.BlockTree.WaitForNewBlock(chain.CancellationToken); chain.MainProcessingContext.GenesisLoader.Load(); await newBlockWaiter; @@ -173,7 +173,16 @@ protected override ContainerBuilder ConfigureContainer(ContainerBuilder builder, .AddSingleton() .AddSingleton() .AddSingleton() - .AddScoped() + .AddScoped(ctx => + new XdcTestGenesisBuilder( + ctx.Resolve(), + ctx.Resolve(), + ctx.Resolve(), + ctx.Resolve>().ToArray(), + ctx.Resolve(), + MasterNodeCandidates + ) + ) .AddSingleton() .AddSingleton((ctx) => new CandidateContainer(MasterNodeCandidates)) .AddSingleton(ctx => @@ -218,6 +227,7 @@ private IXdcReleaseSpec WrapReleaseSpec(IReleaseSpec spec) xdcSpec.LimitPenaltyEpoch = 2; xdcSpec.MinimumSigningTx = 1; xdcSpec.GasLimitBoundDivisor = 1024; + xdcSpec.BlockSignerContract = new Address("0x0000000000000000000000000000000000000089"); V2ConfigParams[] v2ConfigParams = [ new V2ConfigParams { @@ -263,6 +273,8 @@ private IXdcReleaseSpec WrapReleaseSpec(IReleaseSpec spec) ]; xdcSpec.V2Configs = v2ConfigParams.ToList(); + xdcSpec.ValidateChainId = false; + xdcSpec.Reward = 5000; return xdcSpec; } @@ -302,7 +314,8 @@ private class XdcTestGenesisBuilder( IWorldState state, ISnapshotManager snapshotManager, IGenesisPostProcessor[] postProcessors, - Configuration testConfiguration + Configuration testConfiguration, + List masterNodeCandidates ) : IGenesisBuilder { public Block Build() @@ -311,6 +324,11 @@ public Block Build() state.CreateAccount(TestItem.AddressB, testConfiguration.AccountInitialValue); state.CreateAccount(TestItem.AddressC, testConfiguration.AccountInitialValue); + foreach (PrivateKey candidate in masterNodeCandidates) + { + state.CreateAccount(candidate.Address, testConfiguration.AccountInitialValue); + } + IXdcReleaseSpec? finalSpec = (IXdcReleaseSpec)specProvider.GetFinalSpec(); XdcBlockHeaderBuilder xdcBlockHeaderBuilder = new(); diff --git a/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/RewardTests.cs b/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/RewardTests.cs new file mode 100644 index 00000000000..89b1b5d173a --- /dev/null +++ b/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/RewardTests.cs @@ -0,0 +1,249 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Linq; +using System.Threading.Tasks; +using FluentAssertions; +using Nethermind.Consensus.Rewards; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Test.Builders; +using Nethermind.Crypto; +using Nethermind.Int256; +using Nethermind.Xdc.Contracts; +using Nethermind.Xdc.Spec; +using Nethermind.Xdc.Test.Helpers; +using Nethermind.Xdc.Types; +using NSubstitute; +using NUnit.Framework; + +namespace Nethermind.Xdc.Test.ModuleTests; + +public class RewardTests +{ + [Test] + public async Task TestHookRewardV2() + { + var chain = await XdcTestBlockchain.Create(); + var masternodeVotingContract = Substitute.For(); + var rc = new XdcRewardCalculator( + chain.EpochSwitchManager, + chain.SpecProvider, + chain.BlockTree, + masternodeVotingContract + ); + var head = (XdcBlockHeader)chain.BlockTree.Head!.Header; + IXdcReleaseSpec spec = chain.SpecProvider.GetXdcSpec(head, chain.XdcContext.CurrentRound); + var epochLength = spec.EpochLength; + + // Add blocks up to epochLength (E) + 15 and create a signing tx that will be inserted in the next block + await chain.AddBlocks(epochLength + 15 - 3); + var header915 = chain.BlockTree.Head!.Header as XdcBlockHeader; + Assert.That(header915, Is.Not.Null); + PrivateKey signer915 = GetSignerFromMasternodes(chain, header915, spec); + Address owner = signer915.Address; + masternodeVotingContract.GetCandidateOwner(Arg.Any(), signer915.Address).Returns(owner); + await chain.AddBlock(BuildSigningTx( + spec.BlockSignerContract, + header915.Number, + header915.Hash ?? header915.CalculateHash().ToHash256(), + signer915)); + + // Add blocks up until 3E and evaluate rewards at this checkpoint + // Save block 3E - 15 for second part of the test + await chain.AddBlocks(2 * epochLength - 31); + var header2685 = chain.BlockTree.Head!.Header as XdcBlockHeader; + Assert.That(header2685, Is.Not.Null); + PrivateKey signer2685 = GetSignerFromMasternodes(chain, header2685, spec); + Address owner2 = signer2685.Address; + masternodeVotingContract.GetCandidateOwner(Arg.Any(), signer2685.Address).Returns(owner2); + // Continue adding blocks up until 3E + await chain.AddBlocks(15); + Block block2700 = chain.BlockTree.Head!; + var header2700 = block2700.Header as XdcBlockHeader; + Assert.That(header2700, Is.Not.Null); + + BlockReward[] rewardsAt2700 = rc.CalculateRewards(block2700); + + // Expect exactly 2 entries: one for the masternode owner and one for foundation + Address foundation = spec.FoundationWallet; + foundation.Should().NotBe(Address.Zero); + + Assert.That(rewardsAt2700, Has.Length.EqualTo(2)); + rewardsAt2700.Length.Should().Be(2); + + UInt256 total = rewardsAt2700.Aggregate(UInt256.Zero, (acc, r) => acc + r.Value); + UInt256 ownerReward = rewardsAt2700.Single(r => r.Address == owner).Value; + UInt256 foundationReward = rewardsAt2700.Single(r => r.Address == foundation).Value; + + // Check 90/10 split + Assert.That(foundationReward, Is.EqualTo(total / 10)); + Assert.That(ownerReward, Is.EqualTo(total * 90 / 100)); + + // === Second part of the test: signing hash in a different epoch still counts === + + Transaction signingTx2 = BuildSigningTx( + spec.BlockSignerContract, + header2685.Number, + header2685.Hash!, + signer2685); + + // Place signingTx2 in block 3E + 16 (different epoch than the signed block) + await chain.AddBlocks(15); + await chain.AddBlock(signingTx2); + + // Add blocks up until 4E and check rewards + await chain.AddBlocks(epochLength - 16); + Block block3600 = chain.BlockTree.Head!; + var header3600 = block3600.Header as XdcBlockHeader; + Assert.That(header3600, Is.Not.Null); + BlockReward[] rewardsAt3600 = rc.CalculateRewards(block3600); + + // Same expectations: exactly two outputs with 90/10 split + // Since this only counts signing txs from 2E to 3E, only signingTx2 should get counted + Assert.That(rewardsAt3600, Has.Length.EqualTo(2)); + UInt256 total2 = rewardsAt3600.Aggregate(UInt256.Zero, (acc, r) => acc + r.Value); + UInt256 ownerReward2 = rewardsAt3600.Single(r => r.Address == owner2).Value; + UInt256 foundationReward2 = rewardsAt3600.Single(r => r.Address == foundation).Value; + + Assert.That(foundationReward2, Is.EqualTo(total2 / 10)); + Assert.That(ownerReward2, Is.EqualTo(total2 * 90 / 100)); + + // === Third part of the test: if no signing tx, reward should be empty === + + // Add blocks up to 5E and check rewards + await chain.AddBlocks(epochLength); + Block block4500 = chain.BlockTree.Head!; + BlockReward[] rewardsAt4500 = rc.CalculateRewards(block4500); + // If no valid signing txs were counted for that epoch, expect no rewards. + rewardsAt4500.Should().BeEmpty(); + } + + [Test] + public async Task TestHookRewardV2SplitReward() + { + var chain = await XdcTestBlockchain.Create(); + var masternodeVotingContract = Substitute.For(); + var rc = new XdcRewardCalculator( + chain.EpochSwitchManager, + chain.SpecProvider, + chain.BlockTree, + masternodeVotingContract + ); + + var head = (XdcBlockHeader)chain.BlockTree.Head!.Header; + IXdcReleaseSpec spec = chain.SpecProvider.GetXdcSpec(head, chain.XdcContext.CurrentRound); + var epochLength = spec.EpochLength; + + // === Layout (mirrors Go test intent) === + // - Insert 1 signing tx for header (E + 15) signed by signerA into block (E + 16) + // - Insert 2 signing txs (one for header (E + 15), one for header (2E - 15)) signed by signerB into block (2E - 1) + // - Verify: rewards at (3E) split 1:2 between A:B with 90/10 owner/foundation + + // Move to block (E + 15) + await chain.AddBlocks(epochLength + 15 - 3); + var header915 = (XdcBlockHeader)chain.BlockTree.Head!.Header; + + EpochSwitchInfo? epochInfo = chain.EpochSwitchManager.GetEpochSwitchInfo(header915); + Assert.That(epochInfo, Is.Not.Null); + PrivateKey[] masternodes = chain.TakeRandomMasterNodes(spec, epochInfo); + PrivateKey signerA = masternodes.First(); + PrivateKey signerB = masternodes.Last(); + Address ownerA = signerA.Address; + Address ownerB = signerB.Address; + masternodeVotingContract.GetCandidateOwner(Arg.Any(), signerA.Address).Returns(ownerA); + masternodeVotingContract.GetCandidateOwner(Arg.Any(), signerB.Address).Returns(ownerB); + + // Insert 1 signing tx for header (E + 15) in block (E + 16) + Transaction txA = BuildSigningTx( + spec.BlockSignerContract, + header915.Number, + header915.Hash ?? header915.CalculateHash().ToHash256(), + signerA); + await chain.AddBlock(txA); // advances to (E + 16) + + // Move to block (2E - 15) to capture that header as well + var currentNumber = chain.BlockTree.Head!.Number; + await chain.AddBlocks(epochLength - 31); + var header1785 = (XdcBlockHeader)chain.BlockTree.Head!.Header; + + // Prepare two signing txs signed by signerB: + // - for header (E + 15) + // - for header (2E - 15) + Transaction txB1 = BuildSigningTx( + spec.BlockSignerContract, + header915.Number, + header915.Hash!, + signerB); + + Transaction txB2 = BuildSigningTx( + spec.BlockSignerContract, + header1785.Number, + header1785.Hash!, + signerB, + 1); + + // Advance to (2E - 2), then add a block with both signerB txs to be at (2E - 1) + await chain.AddBlocks(13); + await chain.AddBlock(txB1, txB2); // now at (2E - 1) + + // Rewards at (3E) should exist with split 1:2 across A:B and 90/10 owner/foundation + await chain.AddBlocks(epochLength + 1); // from (2E - 1) to (3E) + Block block2700 = chain.BlockTree.Head!; + BlockReward[] rewards = rc.CalculateRewards(block2700); + + Address foundation = spec.FoundationWallet; + + // Expect exactly 3 entries: ownerA, ownerB, foundation. + Assert.That(rewards.Length, Is.EqualTo(3)); + + // Calculate exact rewards for each address + UInt256 totalRewards = (UInt256)spec.Reward * Unit.Ether; + UInt256 signerAReward = totalRewards / 3; + UInt256 ownerAReward = signerAReward * 90 / 100; + UInt256 foundationReward = signerAReward / 10; + UInt256 signerBReward = totalRewards * 2 / 3; + UInt256 ownerBReward = signerBReward * 90 / 100; + foundationReward += signerBReward / 10; + + foreach (BlockReward reward in rewards) + { + if (reward.Address == ownerA) Assert.That(reward.Value, Is.EqualTo(ownerAReward)); + if (reward.Address == ownerB) Assert.That(reward.Value, Is.EqualTo(ownerBReward)); + if (reward.Address == foundation) Assert.That(reward.Value, Is.EqualTo(foundationReward)); + } + } + + private static Transaction BuildSigningTx(Address contract, long blockNumber, Hash256 blockHash, PrivateKey signer, long nonce = 0) + { + Span data = stackalloc byte[68]; + // selector = 0xe341eaa4 + data[0] = 0xe3; data[1] = 0x41; data[2] = 0xea; data[3] = 0xa4; + // uint256 blockNumber (big-endian, 32 bytes) + // encode into last 8 bytes of the 32-byte slot + var bn = BitConverter.GetBytes((ulong)blockNumber); + if (BitConverter.IsLittleEndian) Array.Reverse(bn); + // place at bytes [4..35] (offset 4, length 32) + // last 8 bytes of that 32 are the ulong + for (int i = 0; i < 8; i++) data[4 + 24 + i] = bn[i]; + // bytes32 blockHash at [36..67] + blockHash.Bytes.CopyTo(data.Slice(36, 32)); + + return Build.A.Transaction + .WithChainId(0) + .WithNonce((UInt256)nonce) + .WithGasLimit(200000) + .WithData(data.ToArray()) + .To(contract) + .SignedAndResolved(signer) + .TestObject; + } + + private static PrivateKey GetSignerFromMasternodes(XdcTestBlockchain chain, XdcBlockHeader header, IXdcReleaseSpec spec) + { + EpochSwitchInfo? epochInfo = chain.EpochSwitchManager.GetEpochSwitchInfo(header); + Assert.That(epochInfo, Is.Not.Null); + return chain.TakeRandomMasterNodes(spec, epochInfo).First(); + } +} diff --git a/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs b/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs index e1f2fefc54b..b5049e62cb0 100644 --- a/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs +++ b/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Nethermind.Crypto; using Nethermind.Xdc.Contracts; namespace Nethermind.Xdc @@ -35,6 +36,7 @@ public class XdcRewardCalculator( // XDC rule: signing transactions are sampled/merged every N blocks (N=15 on XDC). // Only block numbers that are multiples of MergeSignRange are considered when tallying signers. private const long MergeSignRange = 15; + private static readonly EthereumEcdsa _ethereumEcdsa = new(0); /// /// Calculates block rewards according to XDPoS consensus rules. @@ -57,40 +59,39 @@ public BlockReward[] CalculateRewards(Block block) IXdcReleaseSpec spec = specProvider.GetXdcSpec(xdcHeader, xdcHeader.ExtraConsensusData.BlockRound); if(number == spec.SwitchBlock + 1) return rewards.ToArray(); - var foundationWalletAddr = spec.FoundationWallet; + Address foundationWalletAddr = spec.FoundationWallet; if (foundationWalletAddr == Address.Zero) throw new InvalidOperationException("Foundation wallet address cannot be empty"); var (signers, count) = GetSigningTxCount(number, xdcHeader, spec); - var chainReward = (UInt256)spec.Reward * Unit.Ether; + UInt256 chainReward = (UInt256)spec.Reward * Unit.Ether; Dictionary rewardSigners = CalculateRewardForSigners(chainReward, signers, count); UInt256 totalFoundationWalletReward = UInt256.Zero; foreach (var (signer, reward) in rewardSigners) { (BlockReward holderReward, UInt256 foundationWalletReward) = DistributeRewards(signer, reward, xdcHeader); - //TODO: stateBlock.AddBalance(holderReward) totalFoundationWalletReward += foundationWalletReward; rewards.Add(holderReward); } - rewards.Add(new BlockReward(foundationWalletAddr, totalFoundationWalletReward)); + if(totalFoundationWalletReward > UInt256.Zero) rewards.Add(new BlockReward(foundationWalletAddr, totalFoundationWalletReward)); return rewards.ToArray(); } - public (Dictionary Signers, long Count) GetSigningTxCount(long number, XdcBlockHeader header, IXdcReleaseSpec spec) + private (Dictionary Signers, long Count) GetSigningTxCount(long number, XdcBlockHeader header, IXdcReleaseSpec spec) { - long signEpochCount = 1, rewardEpochCount = 2, epochCount = 0, endBlockNumber = number, startBlockNumber = 0, signingCount = 0; + long signEpochCount = 1, rewardEpochCount = 2, epochCount = 0, endBlockNumber = 0, startBlockNumber = 0, signingCount = 0; var signers = new Dictionary(); var blockNumberToHash = new Dictionary(); var hashToSigningAddress = new Dictionary>(); var masternodes = new HashSet
(); if (number == 0) return (signers, signingCount); - var h = header; + XdcBlockHeader h = header; for (long i = number - 1; i >= 0; i--) { - var parentHash = h.ParentHash; - h = blockTree.FindHeader(parentHash, i) as XdcBlockHeader; + Hash256 parentHash = h.ParentHash; + h = blockTree.FindHeader(parentHash!, i) as XdcBlockHeader; if (h == null) throw new InvalidOperationException($"Header with hash {parentHash} not found"); if (epochSwitchManager.IsEpochSwitchAtBlock(h) && i != spec.SwitchBlock + 1) { @@ -111,15 +112,16 @@ public BlockReward[] CalculateRewards(Block block) blockNumberToHash[i] = h.Hash; if (!_signingTxsCache.TryGet(h.Hash, out Transaction[] signingTxs)) { - var block = blockTree.FindBlock(i); - if (block == null) throw new InvalidOperationException($"Block with hash {h.Hash} not found"); - var txs = block.Transactions; + Block? block = blockTree.FindBlock(i); + if (block == null) throw new InvalidOperationException($"Block with number {i} not found"); + Transaction[] txs = block.Transactions; signingTxs = CacheSigningTxs(h.Hash!, txs, spec); } foreach (Transaction tx in signingTxs) { Hash256 blockHash = ExtractBlockHashFromSigningTxData(tx.Data); + tx.SenderAddress ??= _ethereumEcdsa.RecoverAddress(tx); if (!hashToSigningAddress.ContainsKey(blockHash)) hashToSigningAddress[blockHash] = new HashSet
(); hashToSigningAddress[blockHash].Add(tx.SenderAddress); @@ -131,7 +133,8 @@ public BlockReward[] CalculateRewards(Block block) long start = ((startBlockNumber + MergeSignRange - 1) / MergeSignRange) * MergeSignRange; for (long i = start; i < endBlockNumber; i += MergeSignRange) { - var addrs = hashToSigningAddress[blockNumberToHash[i]]; + if (!blockNumberToHash.TryGetValue(i, out var blockHash)) continue; + if (!hashToSigningAddress.TryGetValue(blockHash, out var addrs)) continue; foreach (Address addr in addrs) { if (!masternodes.Contains(addr)) continue; @@ -145,7 +148,7 @@ public BlockReward[] CalculateRewards(Block block) private Transaction[] CacheSigningTxs(Hash256 hash, Transaction[] txs, IXdcReleaseSpec spec) { - var signingTxs = txs.Where(t => IsSigningTransaction(t, spec)).ToArray(); + Transaction[] signingTxs = txs.Where(t => IsSigningTransaction(t, spec)).ToArray(); _signingTxsCache.Set(hash, signingTxs); return signingTxs; } @@ -163,23 +166,23 @@ private bool IsSigningTransaction(Transaction tx, IXdcReleaseSpec spec) private String ExtractSelectorFromSigningTxData(ReadOnlyMemory data) { - var span = data.Span; + ReadOnlySpan span = data.Span; if (span.Length != 68) throw new ArgumentException("Signing tx calldata must be exactly 68 bytes (4 + 32 + 32).", nameof(data)); // 0..3: selector - var selBytes = span.Slice(0, 4); + ReadOnlySpan selBytes = span.Slice(0, 4); return "0x" + Convert.ToHexString(selBytes).ToLowerInvariant(); } private Hash256 ExtractBlockHashFromSigningTxData(ReadOnlyMemory data) { - var span = data.Span; + ReadOnlySpan span = data.Span; if (span.Length != 68) throw new ArgumentException("Signing tx calldata must be exactly 68 bytes (4 + 32 + 32).", nameof(data)); // 36..67: bytes32 blockHash - var hashBytes = span.Slice(36, 32); + ReadOnlySpan hashBytes = span.Slice(36, 32); return new Hash256(hashBytes); } @@ -212,8 +215,8 @@ private UInt256 CalculateProportionalReward( } // Convert to UInt256 for precision - UInt256 signatures = (UInt256)signatureCount; - UInt256 total = (UInt256)totalSignatures; + var signatures = (UInt256)signatureCount; + var total = (UInt256)totalSignatures; // Calculate: (signatures * totalReward) / total // Order of operations matters to maintain precision @@ -233,8 +236,7 @@ private UInt256 CalculateProportionalReward( // 10% of the reward goes to the foundation wallet UInt256 foundationReward = reward / 10; - - //TODO: Is it possible owner address is the same as foundation wallet address? + return (new BlockReward(owner, masterReward), foundationReward); } } From ba630e3cbcd6d80e1959c53a3086a39110c70cb2 Mon Sep 17 00:00:00 2001 From: cicr99 Date: Thu, 4 Dec 2025 01:22:47 +0100 Subject: [PATCH 21/25] implement hook for reward calculation in hotstuff pipeline --- src/Nethermind/Nethermind.Xdc/XdcHotStuff.cs | 39 +++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Xdc/XdcHotStuff.cs b/src/Nethermind/Nethermind.Xdc/XdcHotStuff.cs index c17b6d1dc3a..6a4f6303330 100644 --- a/src/Nethermind/Nethermind.Xdc/XdcHotStuff.cs +++ b/src/Nethermind/Nethermind.Xdc/XdcHotStuff.cs @@ -11,8 +11,11 @@ using Nethermind.Xdc.Spec; using Nethermind.Xdc.Types; using System; +using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks; +using Nethermind.Consensus.Rewards; +using Nethermind.Core.Crypto; namespace Nethermind.Xdc { @@ -34,6 +37,8 @@ internal class XdcHotStuff : IBlockProducerRunner private readonly ITimeoutTimer _timeoutTimer; private readonly IProcessExitSource _processExit; private readonly ILogger _logger; + private readonly IRewardCalculator _rewardCalculator; + private readonly ConcurrentDictionary _rewardsDone = new(); private CancellationTokenSource? _cancellationTokenSource; private Task? _runTask; @@ -58,7 +63,8 @@ public XdcHotStuff( ISigner signer, ITimeoutTimer timeoutTimer, IProcessExitSource processExit, - ILogManager logManager) + ILogManager logManager, + IRewardCalculator rewardCalculator) { _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); _xdcContext = xdcContext; @@ -71,6 +77,7 @@ public XdcHotStuff( _signer = signer ?? throw new ArgumentNullException(nameof(signer)); _timeoutTimer = timeoutTimer; _processExit = processExit; + _rewardCalculator = rewardCalculator ?? throw new ArgumentNullException(nameof(rewardCalculator)); _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); _lastActivityTime = DateTime.UtcNow; @@ -367,10 +374,40 @@ private void OnNewHeadBlock(object? sender, BlockEventArgs e) //TODO This should probably trigger a sync } + TryRunRewardHookAsync(e.Block, xdcHead); + // Signal new round _lastActivityTime = DateTime.UtcNow; } + private void TryRunRewardHookAsync(Block block, XdcBlockHeader header) + { + // Only run on epoch-switch blocks + if (!_epochSwitchManager.IsEpochSwitchAtBlock(header)) return; + + // Only run once per block hash + if (!_rewardsDone.TryAdd(header.Hash!, 0)) return; + + _ = Task.Run(() => + { + try + { + var rewards = _rewardCalculator.CalculateRewards(block); + + //TODO What to do with the rewards? Save them in DB? + if (rewards.Length == 0) + _logger.Info($"[Rewards] Epoch checkpoint #{block.Number} => no rewards."); + else + _logger.Info($"[Rewards] Epoch checkpoint #{block.Number} => {rewards.Length} reward entries."); + } + catch (Exception ex) + { + _logger.Error($"[Rewards] Failed at checkpoint #{block.Number}", ex); + //TODO Allow retry if desired? _rewardsDone.TryRemove(header.Hash!, out _); + } + }, _cancellationTokenSource?.Token ?? CancellationToken.None); + } + /// /// Check if the current node is the leader for the given round. /// Uses epoch switch manager and spec to determine leader via round-robin rotation. From 3a632bff3fae8cae4e1aa308598b5798d336fb9e Mon Sep 17 00:00:00 2001 From: cicr99 Date: Thu, 4 Dec 2025 10:58:29 +0100 Subject: [PATCH 22/25] refactor and format --- .../TransactionBuilderXdcExtensions.cs | 49 +++++++++++++++++++ .../ModuleTests/RewardTests.cs | 32 ++++-------- src/Nethermind/Nethermind.Xdc/XdcHotStuff.cs | 6 +-- .../Nethermind.Xdc/XdcRewardCalculator.cs | 2 +- 4 files changed, 62 insertions(+), 27 deletions(-) create mode 100644 src/Nethermind/Nethermind.Xdc.Test/Helpers/TransactionBuilderXdcExtensions.cs diff --git a/src/Nethermind/Nethermind.Xdc.Test/Helpers/TransactionBuilderXdcExtensions.cs b/src/Nethermind/Nethermind.Xdc.Test/Helpers/TransactionBuilderXdcExtensions.cs new file mode 100644 index 00000000000..0de5fe077c0 --- /dev/null +++ b/src/Nethermind/Nethermind.Xdc.Test/Helpers/TransactionBuilderXdcExtensions.cs @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Test.Builders; +using Nethermind.Xdc.Spec; + +namespace Nethermind.Xdc.Test.Helpers; + +public static class TransactionBuilderXdcExtensions +{ + // function sign(uint256 _blockNumber, bytes32 _blockHash) + // selector = 0xe341eaa4 + private static ReadOnlySpan SignSelector => new byte[] { 0xE3, 0x41, 0xEA, 0xA4 }; + + /// Sets 'To' to the XDC block-signer contract from the spec. + public static TransactionBuilder ToBlockSignerContract( + this TransactionBuilder b, IXdcReleaseSpec spec) + => b.To(spec.BlockSignerContract); + + /// + /// Appends ABI-encoded calldata for sign(uint256 _blockNumber, bytes32 _blockHash). + /// Calldata = 4-byte selector + 32-byte big-endian uint + 32-byte bytes32 (68 bytes total). + /// + public static TransactionBuilder WithXdcSigningData( + this TransactionBuilder b, long blockNumber, Hash256 blockHash) + => b.WithData(CreateSigningCalldata(blockNumber, blockHash)); + + private static byte[] CreateSigningCalldata(long blockNumber, Hash256 blockHash) + { + Span data = stackalloc byte[68]; // 4 + 32 + 32 + + // 0..3: selector + SignSelector.CopyTo(data); + + // 4..35: uint256 blockNumber (big-endian, right-aligned in 32 bytes) + var be = BitConverter.GetBytes((ulong)blockNumber); + if (BitConverter.IsLittleEndian) Array.Reverse(be); + // last 8 bytes of that 32 are the ulong + for (int i = 0; i < 8; i++) data[4 + 24 + i] = be[i]; + + // 36..67: bytes32 blockHash + blockHash.Bytes.CopyTo(data.Slice(36, 32)); + + return data.ToArray(); + } +} diff --git a/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/RewardTests.cs b/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/RewardTests.cs index 89b1b5d173a..2b1b8731708 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/RewardTests.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/ModuleTests/RewardTests.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; using System.Linq; using System.Threading.Tasks; using FluentAssertions; @@ -45,7 +44,7 @@ public async Task TestHookRewardV2() Address owner = signer915.Address; masternodeVotingContract.GetCandidateOwner(Arg.Any(), signer915.Address).Returns(owner); await chain.AddBlock(BuildSigningTx( - spec.BlockSignerContract, + spec, header915.Number, header915.Hash ?? header915.CalculateHash().ToHash256(), signer915)); @@ -84,7 +83,7 @@ await chain.AddBlock(BuildSigningTx( // === Second part of the test: signing hash in a different epoch still counts === Transaction signingTx2 = BuildSigningTx( - spec.BlockSignerContract, + spec, header2685.Number, header2685.Hash!, signer2685); @@ -157,7 +156,7 @@ public async Task TestHookRewardV2SplitReward() // Insert 1 signing tx for header (E + 15) in block (E + 16) Transaction txA = BuildSigningTx( - spec.BlockSignerContract, + spec, header915.Number, header915.Hash ?? header915.CalculateHash().ToHash256(), signerA); @@ -172,13 +171,13 @@ public async Task TestHookRewardV2SplitReward() // - for header (E + 15) // - for header (2E - 15) Transaction txB1 = BuildSigningTx( - spec.BlockSignerContract, + spec, header915.Number, header915.Hash!, signerB); Transaction txB2 = BuildSigningTx( - spec.BlockSignerContract, + spec, header1785.Number, header1785.Hash!, signerB, @@ -215,27 +214,14 @@ public async Task TestHookRewardV2SplitReward() } } - private static Transaction BuildSigningTx(Address contract, long blockNumber, Hash256 blockHash, PrivateKey signer, long nonce = 0) + private static Transaction BuildSigningTx(IXdcReleaseSpec spec, long blockNumber, Hash256 blockHash, PrivateKey signer, long nonce = 0) { - Span data = stackalloc byte[68]; - // selector = 0xe341eaa4 - data[0] = 0xe3; data[1] = 0x41; data[2] = 0xea; data[3] = 0xa4; - // uint256 blockNumber (big-endian, 32 bytes) - // encode into last 8 bytes of the 32-byte slot - var bn = BitConverter.GetBytes((ulong)blockNumber); - if (BitConverter.IsLittleEndian) Array.Reverse(bn); - // place at bytes [4..35] (offset 4, length 32) - // last 8 bytes of that 32 are the ulong - for (int i = 0; i < 8; i++) data[4 + 24 + i] = bn[i]; - // bytes32 blockHash at [36..67] - blockHash.Bytes.CopyTo(data.Slice(36, 32)); - - return Build.A.Transaction + return Build.A.Transaction .WithChainId(0) .WithNonce((UInt256)nonce) .WithGasLimit(200000) - .WithData(data.ToArray()) - .To(contract) + .WithXdcSigningData(blockNumber, blockHash) + .ToBlockSignerContract(spec) .SignedAndResolved(signer) .TestObject; } diff --git a/src/Nethermind/Nethermind.Xdc/XdcHotStuff.cs b/src/Nethermind/Nethermind.Xdc/XdcHotStuff.cs index 6a4f6303330..022bc2ce2d3 100644 --- a/src/Nethermind/Nethermind.Xdc/XdcHotStuff.cs +++ b/src/Nethermind/Nethermind.Xdc/XdcHotStuff.cs @@ -37,7 +37,7 @@ internal class XdcHotStuff : IBlockProducerRunner private readonly ITimeoutTimer _timeoutTimer; private readonly IProcessExitSource _processExit; private readonly ILogger _logger; - private readonly IRewardCalculator _rewardCalculator; + private readonly IRewardCalculator _rewardCalculator; private readonly ConcurrentDictionary _rewardsDone = new(); private CancellationTokenSource? _cancellationTokenSource; @@ -392,9 +392,9 @@ private void TryRunRewardHookAsync(Block block, XdcBlockHeader header) { try { - var rewards = _rewardCalculator.CalculateRewards(block); + BlockReward[] rewards = _rewardCalculator.CalculateRewards(block); - //TODO What to do with the rewards? Save them in DB? + //TODO Here we should save the rewards, perhaps in DB? if (rewards.Length == 0) _logger.Info($"[Rewards] Epoch checkpoint #{block.Number} => no rewards."); else diff --git a/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs b/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs index b5049e62cb0..a1a4e316ef5 100644 --- a/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs +++ b/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs @@ -236,7 +236,7 @@ private UInt256 CalculateProportionalReward( // 10% of the reward goes to the foundation wallet UInt256 foundationReward = reward / 10; - + return (new BlockReward(owner, masterReward), foundationReward); } } From a1d0dddb942bc6dac1051fb7cacb9fe8f3995c44 Mon Sep 17 00:00:00 2001 From: cicr99 Date: Thu, 4 Dec 2025 11:11:37 +0100 Subject: [PATCH 23/25] format --- src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs b/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs index a1a4e316ef5..1ad387678d4 100644 --- a/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs +++ b/src/Nethermind/Nethermind.Xdc/XdcRewardCalculator.cs @@ -57,7 +57,7 @@ public BlockReward[] CalculateRewards(Block block) var rewards = new List(); var number = xdcHeader.Number; IXdcReleaseSpec spec = specProvider.GetXdcSpec(xdcHeader, xdcHeader.ExtraConsensusData.BlockRound); - if(number == spec.SwitchBlock + 1) return rewards.ToArray(); + if (number == spec.SwitchBlock + 1) return rewards.ToArray(); Address foundationWalletAddr = spec.FoundationWallet; if (foundationWalletAddr == Address.Zero) throw new InvalidOperationException("Foundation wallet address cannot be empty"); @@ -74,7 +74,7 @@ public BlockReward[] CalculateRewards(Block block) totalFoundationWalletReward += foundationWalletReward; rewards.Add(holderReward); } - if(totalFoundationWalletReward > UInt256.Zero) rewards.Add(new BlockReward(foundationWalletAddr, totalFoundationWalletReward)); + if (totalFoundationWalletReward > UInt256.Zero) rewards.Add(new BlockReward(foundationWalletAddr, totalFoundationWalletReward)); return rewards.ToArray(); } @@ -237,7 +237,7 @@ private UInt256 CalculateProportionalReward( // 10% of the reward goes to the foundation wallet UInt256 foundationReward = reward / 10; - return (new BlockReward(owner, masterReward), foundationReward); + return (new BlockReward(owner, masterReward), foundationReward); } } } From 9a93a797feb943c601de6ea651012ab8ea8d3f43 Mon Sep 17 00:00:00 2001 From: cicr99 Date: Thu, 4 Dec 2025 11:16:11 +0100 Subject: [PATCH 24/25] fix xdc test --- .../Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs b/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs index e95cfa218f0..520f16b8db7 100644 --- a/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs +++ b/src/Nethermind/Nethermind.Xdc/Contracts/IMasternodeVotingContract.cs @@ -6,7 +6,7 @@ namespace Nethermind.Xdc.Contracts; -internal interface IMasternodeVotingContract +public interface IMasternodeVotingContract { Address[] GetCandidates(BlockHeader blockHeader); UInt256 GetCandidateStake(BlockHeader blockHeader, Address candidate); From 327724a608977e0c2b21cd3b2ea4b054afe6b0af Mon Sep 17 00:00:00 2001 From: cicr99 Date: Thu, 4 Dec 2025 12:08:15 +0100 Subject: [PATCH 25/25] wire IRewardClaculator in ConfigureContainer in XdcTestBlockchain --- .../Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs b/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs index 748926f235d..496e356ba5a 100644 --- a/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs +++ b/src/Nethermind/Nethermind.Xdc.Test/Helpers/XdcTestBlockchain.cs @@ -10,6 +10,7 @@ using Nethermind.Consensus.Comparers; using Nethermind.Consensus.Processing; using Nethermind.Consensus.Producers; +using Nethermind.Consensus.Rewards; using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Core.Test.Blockchain; @@ -194,6 +195,7 @@ protected override ContainerBuilder ConfigureContainer(ContainerBuilder builder, }) .AddSingleton((_) => BlockProducer) //.AddSingleton((_) => BlockProducerRunner) + .AddSingleton() .AddSingleton() .AddSingleton(new ProcessExitSource(TestContext.CurrentContext.CancellationToken)) @@ -353,6 +355,11 @@ public Block Build() } } + private class NullRewardCalculator : IRewardCalculator + { + public BlockReward[] CalculateRewards(Block block) => Array.Empty(); + } + public void ChangeReleaseSpec(Action reconfigure) { reconfigure((XdcReleaseSpec)SpecProvider.GetXdcSpec((XdcBlockHeader)BlockTree.Head!.Header));