public AddBlockResult Insert(Block block) { if (!CanAcceptNewBlocks) { return(AddBlockResult.CannotAccept); } if (block.Number == 0) { throw new InvalidOperationException("Genesis block should not be inserted."); } Rlp newRlp = _blockDecoder.Encode(block); _blockDb.Set(block.Hash, newRlp.Bytes); long expectedNumber = (LowestInsertedBody?.Number - 1 ?? LongConverter.FromString(_syncConfig.PivotNumber ?? "0")); if (block.Number != expectedNumber) { throw new InvalidOperationException($"Trying to insert out of order block {block.Number} when expected number was {expectedNumber}"); } if (block.Number < (LowestInsertedBody?.Number ?? long.MaxValue)) { LowestInsertedBody = block; } return(AddBlockResult.Added); }
public override BlockParameter ReadJson(JsonReader reader, Type objectType, BlockParameter existingValue, bool hasExistingValue, JsonSerializer serializer) { if (reader.Value == null) { return(BlockParameter.Latest); } if (reader.Value.IsNonStringValueType()) { return(new BlockParameter((long)reader.Value)); } string value = reader.Value as string; switch (value) { case "": case { } latest when latest.Equals("latest", StringComparison.InvariantCultureIgnoreCase): return(BlockParameter.Latest); case { } latest when latest.Equals("earliest", StringComparison.InvariantCultureIgnoreCase): return(BlockParameter.Earliest); case { } latest when latest.Equals("pending", StringComparison.InvariantCultureIgnoreCase): return(BlockParameter.Pending); default: return(new BlockParameter(LongConverter.FromString(value))); } }
public void FromJson(string jsonValue) { switch (jsonValue) { case string earliest when string.Equals(earliest, "earliest", StringComparison.InvariantCultureIgnoreCase): Type = BlockParameterType.Earliest; return; case string pending when string.Equals(pending, "pending", StringComparison.InvariantCultureIgnoreCase): Type = BlockParameterType.Pending; return; case string latest when string.Equals(latest, "latest", StringComparison.InvariantCultureIgnoreCase): Type = BlockParameterType.Latest; return; case string empty when string.IsNullOrWhiteSpace(empty): Type = BlockParameterType.Latest; return; case null: Type = BlockParameterType.Latest; return; default: Type = BlockParameterType.BlockNumber; BlockNumber = LongConverter.FromString(jsonValue.Trim('"')); return; } }
public static BlockParameter FromJson(string jsonValue) { switch (jsonValue) { case { } earliest when string.Equals(earliest, "earliest", StringComparison.InvariantCultureIgnoreCase): return(Earliest); case { } pending when string.Equals(pending, "pending", StringComparison.InvariantCultureIgnoreCase): return(Pending); case { } latest when string.Equals(latest, "latest", StringComparison.InvariantCultureIgnoreCase): return(Latest); case { } empty when string.IsNullOrWhiteSpace(empty): return(Latest); case null: return(Latest); case { } hash when hash.Length == 66 && hash.StartsWith("0x"): return(Latest); default: return(new BlockParameter(LongConverter.FromString(jsonValue.Trim('"')))); } }
private void LoadEngine(ChainSpecJson chainSpecJson, ChainSpec chainSpec) { if (chainSpecJson.Engine?.AuthorityRound != null) { chainSpec.SealEngineType = SealEngineType.AuRa; } else if (chainSpecJson.Engine?.Clique != null) { chainSpec.SealEngineType = SealEngineType.Clique; chainSpec.Clique = new CliqueParameters(); chainSpec.Clique.Epoch = chainSpecJson.Engine.Clique.Epoch; chainSpec.Clique.Period = chainSpecJson.Engine.Clique.Period; chainSpec.Clique.Reward = chainSpecJson.Engine.Clique.BlockReward ?? UInt256.Zero; } else if (chainSpecJson.Engine?.Ethash != null) { chainSpec.SealEngineType = SealEngineType.Ethash; chainSpec.Ethash = new EthashParameters(); chainSpec.Ethash.MinimumDifficulty = chainSpecJson.Engine.Ethash.MinimumDifficulty ?? 0L; chainSpec.Ethash.DifficultyBoundDivisor = chainSpecJson.Engine.Ethash.DifficultyBoundDivisor ?? 0x0800L; chainSpec.Ethash.DurationLimit = chainSpecJson.Engine.Ethash.DurationLimit ?? 13L; chainSpec.Ethash.HomesteadTransition = chainSpecJson.Engine.Ethash.HomesteadTransition ?? 0; chainSpec.Ethash.DaoHardforkTransition = chainSpecJson.Engine.Ethash.DaoHardforkTransition; chainSpec.Ethash.DaoHardforkBeneficiary = chainSpecJson.Engine.Ethash.DaoHardforkBeneficiary; chainSpec.Ethash.DaoHardforkAccounts = chainSpecJson.Engine.Ethash.DaoHardforkAccounts ?? new Address[0]; chainSpec.Ethash.Eip100bTransition = chainSpecJson.Engine.Ethash.Eip100bTransition ?? 0L; chainSpec.Ethash.BlockRewards = new Dictionary <long, UInt256>(); foreach (KeyValuePair <string, UInt256> reward in chainSpecJson.Engine.Ethash.BlockReward) { chainSpec.Ethash.BlockRewards.Add(LongConverter.FromString(reward.Key), reward.Value); } chainSpec.Ethash.DifficultyBombDelays = new Dictionary <long, long>(); foreach (KeyValuePair <string, long> reward in chainSpecJson.Engine.Ethash.DifficultyBombDelays) { chainSpec.Ethash.DifficultyBombDelays.Add(LongConverter.FromString(reward.Key), reward.Value); } } else if (chainSpecJson.Engine?.NethDev != null) { chainSpec.SealEngineType = SealEngineType.NethDev; } else { throw new NotSupportedException("unknown seal engine in chainspec"); } }
private void LoadLowestInsertedBody() { long left = 0L; long right = LongConverter.FromString(_syncConfig.PivotNumber ?? "0x0"); Block lowestInsertedBlock = null; while (left != right) { if (_logger.IsDebug) { _logger.Debug($"Finding lowest inserted body - L {left} | R {right}"); } long index = left + (right - left) / 2 + 1; ChainLevelInfo level = LoadLevel(index, true); Block block = level == null ? null : FindBlock(level.BlockInfos[0].BlockHash, false); if (block == null) { left = index; } else { lowestInsertedBlock = block; right = index - 1; } } if (lowestInsertedBlock == null) { if (_logger.IsTrace) { _logger.Trace($"Lowest inserted body is null - L {left} | R {right}"); } LowestInsertedBody = null; } else { if (_logger.IsDebug) { _logger.Debug($"Lowest inserted body is {LowestInsertedBody?.ToString(Block.Format.Short)} {right} - L {left} | R {right}"); } LowestInsertedBody = lowestInsertedBlock; } }
private void LoadLowestInsertedHeader() { long left = 0L; long right = LongConverter.FromString(_syncConfig.PivotNumber ?? "0x0"); ChainLevelInfo lowestInsertedLevel = null; while (left != right) { if (_logger.IsTrace) { _logger.Trace($"Finding lowest inserted header - L {left} | R {right}"); } long index = left + (right - left) / 2 + 1; ChainLevelInfo level = LoadLevel(index, true); if (level == null) { left = index; } else { lowestInsertedLevel = level; right = index - 1L; } } if (lowestInsertedLevel == null) { if (_logger.IsTrace) { _logger.Trace($"Lowest inserted header is null - L {left} | R {right}"); } LowestInsertedHeader = null; } else { BlockInfo blockInfo = lowestInsertedLevel.BlockInfos[0]; LowestInsertedHeader = FindHeader(blockInfo.BlockHash); if (_logger.IsDebug) { _logger.Debug($"Lowest inserted header is {LowestInsertedHeader?.ToString(BlockHeader.Format.Short)} {right} - L {left} | R {right}"); } } }
public override ChainSpecJson.AuraEngineParamsJson.StepDurationJson ReadJson(JsonReader reader, Type objectType, ChainSpecJson.AuraEngineParamsJson.StepDurationJson existingValue, bool hasExistingValue, JsonSerializer serializer) { existingValue ??= new ChainSpecJson.AuraEngineParamsJson.StepDurationJson(); if (reader.TokenType == JsonToken.String || reader.TokenType == JsonToken.Integer) { var stepDuration = serializer.Deserialize <long>(reader); existingValue.Add(0, stepDuration); } else { var stepDurations = serializer.Deserialize <Dictionary <string, long> >(reader); foreach (var stepDuration in stepDurations ?? throw new ArgumentException("Cannot deserialize StepDuration.")) { existingValue.Add(LongConverter.FromString(stepDuration.Key), stepDuration.Value); } } return(existingValue); }
public override ChainSpecJson.BlockRewardJson ReadJson(JsonReader reader, Type objectType, ChainSpecJson.BlockRewardJson existingValue, bool hasExistingValue, JsonSerializer serializer) { existingValue ??= new ChainSpecJson.BlockRewardJson(); if (reader.TokenType == JsonToken.String || reader.TokenType == JsonToken.Integer) { var blockReward = serializer.Deserialize <UInt256>(reader); existingValue.Add(0, blockReward); } else { var blockRewards = serializer.Deserialize <Dictionary <string, UInt256> >(reader); foreach (var blockReward in blockRewards ?? throw new ArgumentException("Cannot deserialize BlockReward.")) { existingValue.Add(LongConverter.FromString(blockReward.Key), blockReward.Value); } } return(existingValue); }
private void LoadEngine(ChainSpecJson chainSpecJson, ChainSpec chainSpec) { AuRaParameters.Validator LoadValidator(ChainSpecJson.AuRaValidatorJson validatorJson, int level = 0) { var validatorType = validatorJson.GetValidatorType(); var validator = new AuRaParameters.Validator() { ValidatorType = validatorType }; switch (validator.ValidatorType) { case AuRaParameters.ValidatorType.List: validator.Addresses = validatorJson.List; break; case AuRaParameters.ValidatorType.Contract: validator.Addresses = new[] { validatorJson.SafeContract }; break; case AuRaParameters.ValidatorType.ReportingContract: validator.Addresses = new[] { validatorJson.Contract }; break; case AuRaParameters.ValidatorType.Multi: if (level != 0) { throw new ArgumentException("AuRa multi validator cannot be inner validator."); } validator.Validators = validatorJson.Multi .ToDictionary(kvp => kvp.Key, kvp => LoadValidator(kvp.Value, level + 1)) .ToImmutableSortedDictionary(); break; default: throw new ArgumentOutOfRangeException(); } return(validator); } if (chainSpecJson.Engine?.AuthorityRound != null) { chainSpec.SealEngineType = SealEngineType.AuRa; chainSpec.AuRa = new AuRaParameters { MaximumUncleCount = chainSpecJson.Engine.AuthorityRound.MaximumUncleCount, MaximumUncleCountTransition = chainSpecJson.Engine.AuthorityRound.MaximumUncleCountTransition, StepDuration = chainSpecJson.Engine.AuthorityRound.StepDuration, BlockReward = chainSpecJson.Engine.AuthorityRound.BlockReward, BlockRewardContractAddress = chainSpecJson.Engine.AuthorityRound.BlockRewardContractAddress, BlockRewardContractTransition = chainSpecJson.Engine.AuthorityRound.BlockRewardContractTransition, BlockRewardContractTransitions = chainSpecJson.Engine.AuthorityRound.BlockRewardContractTransitions, ValidateScoreTransition = chainSpecJson.Engine.AuthorityRound.ValidateScoreTransition, ValidateStepTransition = chainSpecJson.Engine.AuthorityRound.ValidateStepTransition, Validators = LoadValidator(chainSpecJson.Engine.AuthorityRound.Validator), RandomnessContractAddress = chainSpecJson.Engine.AuthorityRound.RandomnessContractAddress, BlockGasLimitContractTransitions = chainSpecJson.Engine.AuthorityRound.BlockGasLimitContractTransitions, }; } else if (chainSpecJson.Engine?.Clique != null) { chainSpec.SealEngineType = SealEngineType.Clique; chainSpec.Clique = new CliqueParameters { Epoch = chainSpecJson.Engine.Clique.Epoch, Period = chainSpecJson.Engine.Clique.Period, Reward = chainSpecJson.Engine.Clique.BlockReward ?? UInt256.Zero }; } else if (chainSpecJson.Engine?.Ethash != null) { chainSpec.SealEngineType = SealEngineType.Ethash; chainSpec.Ethash = new EthashParameters { MinimumDifficulty = chainSpecJson.Engine.Ethash.MinimumDifficulty ?? 0L, DifficultyBoundDivisor = chainSpecJson.Engine.Ethash.DifficultyBoundDivisor ?? 0x0800L, DurationLimit = chainSpecJson.Engine.Ethash.DurationLimit ?? 13L, HomesteadTransition = chainSpecJson.Engine.Ethash.HomesteadTransition ?? 0, DaoHardforkTransition = chainSpecJson.Engine.Ethash.DaoHardforkTransition, DaoHardforkBeneficiary = chainSpecJson.Engine.Ethash.DaoHardforkBeneficiary, DaoHardforkAccounts = chainSpecJson.Engine.Ethash.DaoHardforkAccounts ?? new Address[0], Eip100bTransition = chainSpecJson.Engine.Ethash.Eip100bTransition ?? 0L, BlockRewards = new Dictionary <long, UInt256>() }; foreach (KeyValuePair <string, UInt256> reward in chainSpecJson.Engine.Ethash.BlockReward) { chainSpec.Ethash.BlockRewards.Add(LongConverter.FromString(reward.Key), reward.Value); } chainSpec.Ethash.DifficultyBombDelays = new Dictionary <long, long>(); foreach (KeyValuePair <string, long> reward in chainSpecJson.Engine.Ethash.DifficultyBombDelays) { chainSpec.Ethash.DifficultyBombDelays.Add(LongConverter.FromString(reward.Key), reward.Value); } } else if (chainSpecJson.Engine?.NethDev != null) { chainSpec.SealEngineType = SealEngineType.NethDev; } else { throw new NotSupportedException("unknown seal engine in chainspec"); } }
private int InsertBodies(BodiesSyncBatch batch) { List <Block> validResponses = new List <Block>(); for (int i = 0; i < batch.Response.Length; i++) { BlockBody blockBody = batch.Response[i]; if (blockBody == null) { break; } Block block = new Block(batch.Headers[i], blockBody.Transactions, blockBody.Ommers); if (new TxTrie(block.Transactions).RootHash != block.TxRoot || OmmersHash.Calculate(block) != block.OmmersHash) { if (_logger.IsWarn) { _logger.Warn($"{batch} - reporting INVALID - tx or ommers"); } _syncPeerPool.ReportBreachOfProtocol(batch.ResponseSourcePeer, $"invalid tx or ommers root"); break; } validResponses.Add(block); } int validResponsesCount = validResponses.Count; if (validResponses.Count < batch.Request.Length) { BodiesSyncBatch fillerBatch = new BodiesSyncBatch(); fillerBatch.MinNumber = batch.MinNumber; int originalLength = batch.Request.Length; fillerBatch.Request = new Keccak[originalLength - validResponsesCount]; fillerBatch.Headers = new BlockHeader[originalLength - validResponsesCount]; for (int i = validResponsesCount; i < originalLength; i++) { fillerBatch.Request[i - validResponsesCount] = batch.Request[i]; fillerBatch.Headers[i - validResponsesCount] = batch.Headers[i]; } if (_logger.IsDebug) { _logger.Debug($"{batch} -> FILLER {fillerBatch}"); } _pending.Enqueue(fillerBatch); } if (validResponses.Any()) { long expectedNumber = _blockTree.LowestInsertedBody?.Number - 1 ?? LongConverter.FromString(_syncConfig.PivotNumber ?? "0"); if (validResponses.Last().Number != expectedNumber) { _dependencies.TryAdd(validResponses.Last().Number, validResponses); } else { validResponses.Reverse(); InsertBlocks(validResponses); } if (_blockTree.LowestInsertedBody != null) { _syncReport.FastBlocksBodies.Update(_pivotNumber - _blockTree.LowestInsertedBody.Number + 1); } } if (_logger.IsDebug) { _logger.Debug($"LOWEST_INSERTED {_blockTree.LowestInsertedBody?.Number} | HANDLED {batch}"); } _syncReport.BodiesInQueue.Update(BodiesInQueue); return(validResponsesCount); }
static AuRaParameters.Validator LoadValidator(ChainSpecJson.AuRaValidatorJson validatorJson, int level = 0) { AuRaParameters.ValidatorType validatorType = validatorJson.GetValidatorType(); AuRaParameters.Validator validator = new() { ValidatorType = validatorType }; switch (validator.ValidatorType) { case AuRaParameters.ValidatorType.List: validator.Addresses = validatorJson.List; break; case AuRaParameters.ValidatorType.Contract: validator.Addresses = new[] { validatorJson.SafeContract }; break; case AuRaParameters.ValidatorType.ReportingContract: validator.Addresses = new[] { validatorJson.Contract }; break; case AuRaParameters.ValidatorType.Multi: if (level != 0) { throw new ArgumentException("AuRa multi validator cannot be inner validator."); } validator.Validators = validatorJson.Multi .ToDictionary(kvp => kvp.Key, kvp => LoadValidator(kvp.Value, level + 1)) .ToImmutableSortedDictionary(); break; default: throw new ArgumentOutOfRangeException(); } return(validator); } if (chainSpecJson.Engine?.AuthorityRound != null) { chainSpec.SealEngineType = SealEngineType.AuRa; chainSpec.AuRa = new AuRaParameters { MaximumUncleCount = chainSpecJson.Engine.AuthorityRound.MaximumUncleCount, MaximumUncleCountTransition = chainSpecJson.Engine.AuthorityRound.MaximumUncleCountTransition, StepDuration = chainSpecJson.Engine.AuthorityRound.StepDuration, BlockReward = chainSpecJson.Engine.AuthorityRound.BlockReward, BlockRewardContractAddress = chainSpecJson.Engine.AuthorityRound.BlockRewardContractAddress, BlockRewardContractTransition = chainSpecJson.Engine.AuthorityRound.BlockRewardContractTransition, BlockRewardContractTransitions = chainSpecJson.Engine.AuthorityRound.BlockRewardContractTransitions, ValidateScoreTransition = chainSpecJson.Engine.AuthorityRound.ValidateScoreTransition, ValidateStepTransition = chainSpecJson.Engine.AuthorityRound.ValidateStepTransition, Validators = LoadValidator(chainSpecJson.Engine.AuthorityRound.Validator), RandomnessContractAddress = chainSpecJson.Engine.AuthorityRound.RandomnessContractAddress, BlockGasLimitContractTransitions = chainSpecJson.Engine.AuthorityRound.BlockGasLimitContractTransitions, TwoThirdsMajorityTransition = chainSpecJson.Engine.AuthorityRound.TwoThirdsMajorityTransition ?? AuRaParameters.TransitionDisabled, PosdaoTransition = chainSpecJson.Engine.AuthorityRound.PosdaoTransition ?? AuRaParameters.TransitionDisabled, RewriteBytecode = chainSpecJson.Engine.AuthorityRound.RewriteBytecode, }; } else if (chainSpecJson.Engine?.Clique != null) { chainSpec.SealEngineType = SealEngineType.Clique; chainSpec.Clique = new CliqueParameters { Epoch = chainSpecJson.Engine.Clique.Epoch, Period = chainSpecJson.Engine.Clique.Period, Reward = chainSpecJson.Engine.Clique.BlockReward ?? UInt256.Zero }; } else if (chainSpecJson.Engine?.Ethash != null) { chainSpec.SealEngineType = SealEngineType.Ethash; chainSpec.Ethash = new EthashParameters { MinimumDifficulty = chainSpecJson.Engine.Ethash.MinimumDifficulty ?? 0L, DifficultyBoundDivisor = chainSpecJson.Engine.Ethash.DifficultyBoundDivisor ?? 0x0800L, DurationLimit = chainSpecJson.Engine.Ethash.DurationLimit ?? 13L, HomesteadTransition = chainSpecJson.Engine.Ethash.HomesteadTransition ?? 0, DaoHardforkTransition = chainSpecJson.Engine.Ethash.DaoHardforkTransition, DaoHardforkBeneficiary = chainSpecJson.Engine.Ethash.DaoHardforkBeneficiary, DaoHardforkAccounts = chainSpecJson.Engine.Ethash.DaoHardforkAccounts ?? Array.Empty <Address>(), Eip100bTransition = chainSpecJson.Engine.Ethash.Eip100bTransition ?? 0L, FixedDifficulty = chainSpecJson.Engine.Ethash.FixedDifficulty, BlockRewards = chainSpecJson.Engine.Ethash.BlockReward }; chainSpec.Ethash.DifficultyBombDelays = new Dictionary <long, long>(); if (chainSpecJson.Engine.Ethash.DifficultyBombDelays != null) { foreach (KeyValuePair <string, long> reward in chainSpecJson.Engine.Ethash.DifficultyBombDelays) { chainSpec.Ethash.DifficultyBombDelays.Add(LongConverter.FromString(reward.Key), reward.Value); } } } else if (chainSpecJson.Engine?.NethDev != null) { chainSpec.SealEngineType = SealEngineType.NethDev; } var customEngineType = chainSpecJson.Engine?.CustomEngineData?.FirstOrDefault().Key; if (!string.IsNullOrEmpty(customEngineType)) { chainSpec.SealEngineType = customEngineType; } if (string.IsNullOrEmpty(chainSpec.SealEngineType)) { throw new NotSupportedException("unknown seal engine in chainspec"); } }