Пример #1
0
        public long DataGasCost(ReadOnlyMemory <byte> inputData, IReleaseSpec releaseSpec)
        {
            try
            {
                Span <byte> extendedInput = stackalloc byte[96];
                inputData.Slice(0, Math.Min(96, inputData.Length)).Span
                .CopyTo(extendedInput.Slice(0, Math.Min(96, inputData.Length)));

                UInt256 baseLength    = new(extendedInput.Slice(0, 32), true);
                UInt256 expLength     = new(extendedInput.Slice(32, 32), true);
                UInt256 modulusLength = new(extendedInput.Slice(64, 32), true);

                UInt256 complexity = MultComplexity(UInt256.Max(baseLength, modulusLength));

                byte[] expSignificantBytes = inputData.Span.SliceWithZeroPaddingEmptyOnError(96 + (int)baseLength, (int)UInt256.Min(expLength, 32));

                UInt256 lengthOver32 = expLength <= 32 ? 0 : expLength - 32;
                UInt256 adjusted     = AdjustedExponentLength(lengthOver32, expSignificantBytes);
                UInt256 gas          = complexity * UInt256.Max(adjusted, UInt256.One) / 20;
                return(gas > long.MaxValue ? long.MaxValue : (long)gas);
            }
            catch (OverflowException)
            {
                return(long.MaxValue);
            }
        }
Пример #2
0
        protected virtual Block PrepareBlock(BlockHeader parent)
        {
            UInt256     timestamp  = UInt256.Max(parent.Timestamp + 1, _timestamper.UnixTime.Seconds);
            UInt256     difficulty = CalculateDifficulty(parent, timestamp);
            BlockHeader header     = new BlockHeader(
                parent.Hash,
                Keccak.OfAnEmptySequenceRlp,
                _sealer.Address,
                difficulty,
                parent.Number + 1,
                _gasLimitCalculator.GetGasLimit(parent),
                timestamp,
                Encoding.UTF8.GetBytes("Nethermind"))
            {
                TotalDifficulty = parent.TotalDifficulty + difficulty,
                Author          = _sealer.Address
            };

            if (Logger.IsDebug)
            {
                Logger.Debug($"Setting total difficulty to {parent.TotalDifficulty} + {difficulty}.");
            }

            var   transactions = _txSource.GetTransactions(parent, header.GasLimit);
            Block block        = new Block(header, transactions, Array.Empty <BlockHeader>());

            header.TxRoot = new TxTrie(block.Transactions).RootHash;
            return(block);
        }
Пример #3
0
        /// <summary>
        /// def calculate_iteration_count(exponent_length, exponent):
        /// iteration_count = 0
        /// if exponent_length &lt;= 32 and exponent == 0: iteration_count = 0
        /// elif exponent_length &lt;= 32: iteration_count = exponent.bit_length() - 1
        /// elif exponent_length > 32: iteration_count = (8 * (exponent_length - 32)) + ((exponent & (2**256 - 1)).bit_length() - 1)
        /// return max(iteration_count, 1)
        /// </summary>
        /// <param name="exponentLength"></param>
        /// <param name="exponent"></param>
        /// <returns></returns>
        private static UInt256 CalculateIterationCount(UInt256 exponentLength, UInt256 exponent)
        {
            try
            {
                UInt256 iterationCount;
                if (exponentLength <= 32)
                {
                    if (!exponent.IsZero)
                    {
                        iterationCount = (UInt256)(exponent.BitLen - 1);
                    }
                    else
                    {
                        iterationCount = UInt256.Zero;
                    }
                }
                else
                {
                    int bitLength = (exponent & UInt256.MaxValue).BitLen;
                    if (bitLength > 0)
                    {
                        bitLength--;
                    }

                    iterationCount = 8 * (exponentLength - 32) + (UInt256)bitLength;
                }

                return(UInt256.Max(iterationCount, UInt256.One));
            }
            catch (OverflowException)
            {
                return(UInt256.MaxValue);
            }
        }
Пример #4
0
        protected virtual Block PrepareBlock(BlockHeader parent)
        {
            UInt256     timestamp  = _timestamper.EpochSeconds;
            UInt256     difficulty = CalculateDifficulty(parent, timestamp);
            BlockHeader header     = new BlockHeader(
                parent.Hash,
                Keccak.OfAnEmptySequenceRlp,
                Address.Zero,
                difficulty,
                parent.Number + 1,
                GetGasLimit(parent),
                UInt256.Max(parent.Timestamp + 1, _timestamper.EpochSeconds),
                Encoding.UTF8.GetBytes("Nethermind"))
            {
                TotalDifficulty = parent.TotalDifficulty + difficulty
            };

            if (Logger.IsDebug)
            {
                Logger.Debug($"Setting total difficulty to {parent.TotalDifficulty} + {difficulty}.");
            }

            var   transactions = _txSource.GetTransactions(parent, header.GasLimit);
            Block block        = new Block(header, transactions, new BlockHeader[0]);

            header.TxRoot = new TxTrie(block.Transactions).RootHash;
            return(block);
        }
Пример #5
0
        public BlockchainBridge.CallOutput EstimateGas(BlockHeader header, Transaction tx, CancellationToken cancellationToken)
        {
            ReadOnlyTxProcessingEnv txProcessingEnv =
                new(_dbProvider, _trieStore, _blockTree, _specProvider, _logManager);
            ITransactionProcessor transactionProcessor = txProcessingEnv.Build(_stateProvider.StateRoot);

            EstimateGasTracer estimateGasTracer = new();

            (bool Success, string Error)tryCallResult = TryCallAndRestore(
                transactionProcessor,
                txProcessingEnv,
                header,
                UInt256.Max(header.Timestamp + 1, _timestamper.UnixTime.Seconds),
                tx,
                true,
                estimateGasTracer.WithCancellation(cancellationToken));

            GasEstimator gasEstimator = new(transactionProcessor, _stateProvider, _specProvider);
            long         estimate     = gasEstimator.Estimate(tx, header, estimateGasTracer);

            return(new BlockchainBridge.CallOutput
            {
                Error = tryCallResult.Success ? estimateGasTracer.Error : tryCallResult.Error,
                GasSpent = estimate,
                InputError = !tryCallResult.Success
            });
        }
Пример #6
0
        public ValueTask <Keccak> SendTransaction(Transaction tx, TxHandlingOptions txHandlingOptions)
        {
            UInt256 minGasPrice = CurrentMinGasPrice();
            UInt256 txGasPrice  = minGasPrice * _percentDelta / 100;

            tx.GasPrice = UInt256.Max(txGasPrice, _miningConfig.MinGasPrice);
            return(_txSender.SendTransaction(tx, txHandlingOptions));
        }
Пример #7
0
        /// <summary>
        /// def calculate_multiplication_complexity(base_length, modulus_length):
        /// max_length = max(base_length, modulus_length)
        /// words = math.ceil(max_length / 8)
        /// return words**2
        /// </summary>
        /// <returns></returns>
        private static UInt256 MultComplexity(UInt256 baseLength, UInt256 modulusLength)
        {
            UInt256 maxLength = UInt256.Max(baseLength, modulusLength);

            UInt256.Mod(maxLength, 8, out UInt256 mod8);
            UInt256 words = (maxLength / 8) + ((mod8.IsZero) ? UInt256.Zero : UInt256.One);

            return(words * words);
        }
Пример #8
0
        public CallOutput EstimateGas(BlockHeader header, Transaction tx)
        {
            EstimateGasTracer estimateGasTracer = new EstimateGasTracer(_cancellationToken);

            CallAndRestore(header, tx, UInt256.Max(header.Timestamp + 1, _timestamper.EpochSeconds), estimateGasTracer);
            long estimate = estimateGasTracer.CalculateEstimate(tx);

            return(new CallOutput {
                Error = estimateGasTracer.Error, GasSpent = estimate
            });
        }
Пример #9
0
        public ValueTask <Keccak> SendTransaction(Transaction tx, TxHandlingOptions txHandlingOptions)
        {
            (UInt256 minFeeCap, UInt256 minGasPremium) = CurrentMinGas();
            UInt256 txFeeCap     = minFeeCap * _percentDelta / 100;
            UInt256 txGasPremium = minGasPremium * _percentDelta / 100;

            tx.DecodedFeeCap = UInt256.Max(txFeeCap, _miningConfig.MinGasPrice);
            tx.GasPrice      = txGasPremium;
            tx.Type          = TxType.EIP1559;
            return(_txSender.SendTransaction(tx, txHandlingOptions));
        }
Пример #10
0
        public void HintBlock(Keccak hash, UInt256 number, NodeId receivedFrom)
        {
            if (!_peers.TryGetValue(receivedFrom, out PeerInfo peerInfo))
            {
                if (_logger.IsTrace)
                {
                    _logger.Trace($"Received a block hint from an unknown peer {receivedFrom}, ignoring");
                }
                return;
            }

            peerInfo.NumberAvailable = UInt256.Max(number, peerInfo.NumberAvailable);
        }
Пример #11
0
        public static UInt256 CalculateBaseFee(BlockHeader parent, IReleaseSpec spec)
        {
            UInt256 expectedBaseFee = UInt256.Zero;

            if (spec.IsEip1559Enabled)
            {
                UInt256 parentBaseFee = parent.BaseFee;
                long    gasDelta;
                UInt256 feeDelta;
                long    parentGasTarget = parent.GasLimit;

                // # check if the base fee is correct
                //   if parent_gas_used == parent_gas_target:
                //   expected_base_fee = parent_base_fee
                //   elif parent_gas_used > parent_gas_target:
                //   gas_delta = parent_gas_used - parent_gas_target
                //   fee_delta = max(parent_base_fee * gas_delta // parent_gas_target // BASE_FEE_MAX_CHANGE_DENOMINATOR, 1)
                //   expected_base_fee = parent_base_fee + fee_delta
                //   else:
                //   gas_delta = parent_gas_target - parent_gas_used
                //   fee_delta = parent_base_fee * gas_delta // parent_gas_target // BASE_FEE_MAX_CHANGE_DENOMINATOR
                //   expected_base_fee = parent_base_fee - fee_delta
                //   assert expected_base_fee == block.base_fee, 'invalid block: base fee not correct'

                if (parent.GasUsed == parentGasTarget)
                {
                    expectedBaseFee = parent.BaseFee;
                }
                else if (parent.GasUsed > parentGasTarget)
                {
                    gasDelta = parent.GasUsed - parentGasTarget;
                    feeDelta = UInt256.Max(
                        parentBaseFee * (UInt256)gasDelta / (UInt256)parentGasTarget / BaseFeeMaxChangeDenominator,
                        UInt256.One);
                    expectedBaseFee = parentBaseFee + feeDelta;
                }
                else
                {
                    gasDelta        = parentGasTarget - parent.GasUsed;
                    feeDelta        = parentBaseFee * (UInt256)gasDelta / (UInt256)parentGasTarget / BaseFeeMaxChangeDenominator;
                    expectedBaseFee = parentBaseFee - feeDelta;
                }

                if (spec.Eip1559TransitionBlock == parent.Number + 1)
                {
                    expectedBaseFee = 1.GWei();
                }
            }

            return(expectedBaseFee);
        }
Пример #12
0
        public static UInt256 Calculate(BlockHeader parent, IReleaseSpec spec)
        {
            UInt256 expectedBaseFee = parent.BaseFeePerGas;

            if (spec.IsEip1559Enabled)
            {
                UInt256 parentBaseFee = parent.BaseFeePerGas;
                long    gasDelta;
                UInt256 feeDelta;
                bool    isForkBlockNumber = spec.Eip1559TransitionBlock == parent.Number + 1;
                long    parentGasTarget   = parent.GasLimit / Eip1559Constants.ElasticityMultiplier;
                if (isForkBlockNumber)
                {
                    parentGasTarget = parent.GasLimit;
                }

                if (parent.GasUsed == parentGasTarget)
                {
                    expectedBaseFee = parent.BaseFeePerGas;
                }
                else if (parent.GasUsed > parentGasTarget)
                {
                    gasDelta = parent.GasUsed - parentGasTarget;
                    feeDelta = UInt256.Max(
                        parentBaseFee * (UInt256)gasDelta / (UInt256)parentGasTarget / Eip1559Constants.BaseFeeMaxChangeDenominator,
                        UInt256.One);
                    expectedBaseFee = parentBaseFee + feeDelta;
                }
                else
                {
                    gasDelta        = parentGasTarget - parent.GasUsed;
                    feeDelta        = parentBaseFee * (UInt256)gasDelta / (UInt256)parentGasTarget / Eip1559Constants.BaseFeeMaxChangeDenominator;
                    expectedBaseFee = UInt256.Max(parentBaseFee - feeDelta, 0);
                }

                if (isForkBlockNumber)
                {
                    expectedBaseFee = Eip1559Constants.ForkBaseFee;
                }

                if (spec.Eip1559BaseFeeMinValue.HasValue)
                {
                    expectedBaseFee = UInt256.Max(expectedBaseFee, spec.Eip1559BaseFeeMinValue.Value);
                }
            }

            return(expectedBaseFee);
        }
Пример #13
0
        protected override UInt256 CalculateDifficulty(BlockHeader parent, UInt256 timestamp)
        {
            UInt256 difficulty;

            if (_miningConfig.RandomizedBlocks)
            {
                UInt256 change = new UInt256((ulong)(_random.Next(100) + 50));
                difficulty = UInt256.Max(1000, UInt256.Max(parent.Difficulty, 1000) / 100 * change);
            }
            else
            {
                difficulty = UInt256.One;
            }

            return(difficulty);
        }
Пример #14
0
        public CallOutput EstimateGas(BlockHeader header, Transaction tx, CancellationToken cancellationToken)
        {
            EstimateGasTracer estimateGasTracer = new EstimateGasTracer();

            CallAndRestore(
                header,
                header.Number + 1,
                UInt256.Max(header.Timestamp + 1, _timestamper.UnixTime.Seconds),
                tx,
                estimateGasTracer.WithCancellation(cancellationToken));

            long estimate = estimateGasTracer.CalculateEstimate(tx);

            return(new CallOutput {
                Error = estimateGasTracer.Error, GasSpent = estimate
            });
        }
Пример #15
0
        public CallOutput EstimateGas(BlockHeader header, Transaction tx, CancellationToken cancellationToken)
        {
            EstimateGasTracer estimateGasTracer = new();

            (bool Success, string Error)tryCallResult = TryCallAndRestore(
                header,
                header.Number + 1,
                UInt256.Max(header.Timestamp + 1, _timestamper.UnixTime.Seconds),
                tx,
                estimateGasTracer.WithCancellation(cancellationToken));

            long estimate = estimateGasTracer.CalculateEstimate(tx);

            return(new CallOutput {
                Error = tryCallResult.Success ? estimateGasTracer.Error : tryCallResult.Error, GasSpent = estimate, InputError = !tryCallResult.Success
            });
        }
Пример #16
0
        /// <summary>
        /// def calculate_iteration_count(exponent_length, exponent):
        /// iteration_count = 0
        /// if exponent_length <= 32 and exponent == 0: iteration_count = 0
        /// elif exponent_length <= 32: iteration_count = exponent.bit_length() - 1
        /// elif exponent_length > 32: iteration_count = (8 * (exponent_length - 32)) + ((exponent & (2**256 - 1)).bit_length() - 1)
        /// return max(iteration_count, 1)
        /// </summary>
        /// <param name="exponentLength"></param>
        /// <param name="exponent"></param>
        /// <returns></returns>
        private static UInt256 CalculateIterationCount(int exponentLength, UInt256 exponent)
        {
            UInt256 iterationCount = UInt256.Zero;

            if (exponentLength <= 32)
            {
                if (exponent != 0)
                {
                    iterationCount = (UInt256)(exponent.BitLen - 1);
                }
            }
            else
            {
                iterationCount = (UInt256)(8 * (exponentLength - 32)) + (UInt256)((exponent & UInt256.MaxValue).BitLen - 1);
            }

            return(UInt256.Max(iterationCount, UInt256.One));
        }
Пример #17
0
        public CallOutput EstimateGas(BlockHeader header, Transaction tx, CancellationToken cancellationToken)
        {
            EstimateGasTracer estimateGasTracer = new();

            (bool Success, string Error)tryCallResult = TryCallAndRestore(
                header,
                UInt256.Max(header.Timestamp + 1, _timestamper.UnixTime.Seconds),
                tx,
                true,
                estimateGasTracer.WithCancellation(cancellationToken));

            GasEstimator gasEstimator = new(_transactionProcessor, _stateProvider, _specProvider);
            long         estimate     = gasEstimator.Estimate(tx, header, estimateGasTracer);

            return(new CallOutput
            {
                Error = tryCallResult.Success ? estimateGasTracer.Error : tryCallResult.Error,
                GasSpent = estimate,
                InputError = !tryCallResult.Success
            });
        }
Пример #18
0
        public void AddNewBlock(Block block, NodeId receivedFrom)
        {
            // TODO: validation

            _peers.TryGetValue(receivedFrom, out PeerInfo peerInfo);
            if (peerInfo == null)
            {
                string errorMessage = $"Received a new block from an unknown peer {receivedFrom}";
                _logger.Error(errorMessage);
                return;
            }

            peerInfo.NumberAvailable = UInt256.Max(block.Number, peerInfo.NumberAvailable);
//            peerInfo.Difficulty = UInt256.Max(block.Difficulty, peerInfo.Difficulty);

            lock (_isSyncingLock)
            {
                if (_isSyncing)
                {
                    if (_logger.IsTrace)
                    {
                        _logger.Trace($"Ignoring new block {block.Hash} while syncing");
                    }
                    return;
                }
            }

            if (_logger.IsTrace)
            {
                _logger.Trace($"Adding new block {block.Hash} ({block.Number}) from {receivedFrom}");
            }

            if (block.Number <= _blockTree.BestSuggested.Number + 1)
            {
                if (_logger.IsTrace)
                {
                    _logger.Trace($"Suggesting a block {block.Hash} ({block.Number}) from {receivedFrom} with {block.Transactions.Length} transactions");
                }
                if (_logger.IsTrace)
                {
                    _logger.Trace($"{block}");
                }

                AddBlockResult result = _blockTree.SuggestBlock(block);
                if (_logger.IsInfo)
                {
                    _logger.Info($"{block.Hash} ({block.Number}) adding result is {result}");
                }
                if (result == AddBlockResult.UnknownParent)
                {
                    /* here we want to cover scenario when our peer is reorganizing and sends us a head block
                     * from a new branch and we need to sync previous blocks as we do not know this block's parent */
                    RequestSync();
                }
                else
                {
                    peerInfo.NumberReceived = block.Number;
                }
            }
            else
            {
                if (_logger.IsTrace)
                {
                    _logger.Trace($"Received a block {block.Hash} ({block.Number}) from {receivedFrom} - need to resync");
                }
                RequestSync();
            }
        }
Пример #19
0
//        [DataRow(uint.MaxValue, uint.MaxValue)]
//        [DataRow(ulong.MaxValue, ulong.MaxValue)]
        public void UInt256Test(ulong factorMax, ulong modulusMax)
        {
            var random = new MersenneTwister(0).Create <ulong>();

            for (int i = 0; i < 10000; i++)
            {
                var n     = random.Next(modulusMax - 1) + 1;
                var a     = random.Next(factorMax) % n;
                var b     = random.Next(factorMax) % n;
                var c     = random.Next(factorMax) % n;
                var d     = random.Next(factorMax) % n;
                var s     = (int)(b % 32);
                var value = (UInt256)0;
                Assert.AreEqual((BigInteger)a << s, (UInt256)a << s);
                Assert.AreEqual((BigInteger)a >> s, (UInt256)a >> s);
                Assert.AreEqual((BigInteger)a & b, (UInt256)a & b);
                Assert.AreEqual((BigInteger)a & b, a & (UInt256)b);
                Assert.AreEqual((BigInteger)a & b, (UInt256)a & (UInt256)b);
                Assert.AreEqual((BigInteger)a | b, (UInt256)a | b);
                Assert.AreEqual((BigInteger)a | b, a | (UInt256)b);
                Assert.AreEqual((BigInteger)a | b, (UInt256)a | (UInt256)b);
                Assert.AreEqual((BigInteger)a ^ b, (UInt256)a ^ b);
                Assert.AreEqual((BigInteger)a ^ b, a ^ (UInt256)b);
                Assert.AreEqual((BigInteger)a ^ b, (UInt256)a ^ (UInt256)b);
                if (a <= long.MaxValue)
                {
                    Assert.AreEqual(~(BigInteger)a, (long)~(UInt256)a);
                }
                Assert.AreEqual((BigInteger)a + b, (UInt256)a + b);
                Assert.AreEqual((BigInteger)a + b, a + (UInt256)b);
                Assert.AreEqual((BigInteger)a + b, (UInt256)a + (UInt256)b);
                Assert.AreEqual(((BigInteger)a * n + (BigInteger)b * n) % ((BigInteger)1 << 128), (UInt256)a * n + (UInt256)b * n);
                if (a >= b)
                {
                    Assert.AreEqual((BigInteger)a - b, (UInt256)a - b);
                    Assert.AreEqual((BigInteger)a - b, a - (UInt256)b);
                    Assert.AreEqual((BigInteger)a - b, (UInt256)a - (UInt256)b);
                    Assert.AreEqual((BigInteger)a * n - (BigInteger)b * n, (UInt256)a * n - (UInt256)b * n);
                }
                Assert.AreEqual(+(BigInteger)a, +(Int128)a);
                value = a; Assert.AreEqual((BigInteger)a + 1, ++value);
                value = a; Assert.AreEqual((BigInteger)a, value++);
                value = (UInt256)a * b; Assert.AreEqual((BigInteger)a * b + 1, ++value);
                value = (UInt256)a * b; Assert.AreEqual((BigInteger)a * b, value++);
                if (a > 0)
                {
                    value = a; Assert.AreEqual((BigInteger)a - 1, --value);
                    value = a; Assert.AreEqual((BigInteger)a, value--);
                }
                if (a > 0 && b > 0)
                {
                    value = (UInt256)a * b; Assert.AreEqual((BigInteger)a * b - 1, --value);
                    value = (UInt256)a * b; Assert.AreEqual((BigInteger)a * b, value--);
                }
                if (n <= uint.MaxValue)
                {
                    Assert.AreEqual((BigInteger)a * n, (UInt256)a * (uint)n);
                    Assert.AreEqual((BigInteger)b * n, (UInt256)b * (uint)n);
                    Assert.AreEqual((BigInteger)a * b * n % ((BigInteger)1 << 128), (UInt256)a * b * (uint)n);
                    Assert.AreEqual((BigInteger)n * a, (uint)n * (UInt256)a);
                    Assert.AreEqual((BigInteger)n * b, (uint)n * (UInt256)b);
                    Assert.AreEqual((BigInteger)n * a * b % ((BigInteger)1 << 128), (uint)n * ((UInt256)a * (UInt256)b));
                }
                Assert.AreEqual((BigInteger)a * b, a * (UInt256)b);
                Assert.AreEqual((BigInteger)a * b, (UInt256)a * b);
                Assert.AreEqual((BigInteger)a * b, a * (UInt256)b);
                Assert.AreEqual((BigInteger)a * b, (UInt256)a * (UInt256)b);
                if (b > 0)
                {
                    Assert.AreEqual((BigInteger)a % b, (UInt256)a % b);
                    Assert.AreEqual((BigInteger)a % b, a % (UInt256)b);
                    Assert.AreEqual((BigInteger)a % b, (UInt256)a % (UInt256)b);
                }
                Assert.AreEqual((BigInteger)a * b % n, (UInt256)a * b % n);
                Assert.AreEqual((BigInteger)a * b % n, a * (UInt256)b % n);
                Assert.AreEqual((BigInteger)a * b % n, (UInt256)a * (UInt256)b % (UInt256)n);
                if (c > 0 && d > 0)
                {
                    Assert.AreEqual((BigInteger)a * b / ((BigInteger)c * d), (UInt256)a * (UInt256)b / ((UInt256)c * (UInt256)d));
                    Assert.AreEqual((BigInteger)a * b % ((BigInteger)c * d), (UInt256)a * (UInt256)b % ((UInt256)c * (UInt256)d));
                }
                if (b > 0)
                {
                    Assert.AreEqual((BigInteger)a / b, (UInt256)a / b);
                    Assert.AreEqual((BigInteger)a / b, a / (UInt256)b);
                    Assert.AreEqual((BigInteger)a / b, (UInt256)a / (UInt256)b);
                }
                Assert.AreEqual((BigInteger)a * b / n, (UInt256)a * b / n);
                Assert.AreEqual((BigInteger)a * b / n, a * (UInt256)b / n);
                Assert.AreEqual((BigInteger)a * b / n, (UInt256)a * (UInt256)b / (UInt256)n);
                Assert.AreEqual((BigInteger)a < b, (UInt256)a < b);
                Assert.AreEqual((BigInteger)a < b, a < (UInt256)b);
                Assert.AreEqual((BigInteger)a < b, (UInt256)a < (UInt256)b);
                Assert.AreEqual((BigInteger)a <= b, (UInt256)a <= b);
                Assert.AreEqual((BigInteger)a <= b, a <= (UInt256)b);
                Assert.AreEqual((BigInteger)a <= b, (UInt256)a <= (UInt256)b);
                Assert.AreEqual((BigInteger)a > b, (UInt256)a > b);
                Assert.AreEqual((BigInteger)a > b, a > (UInt256)b);
                Assert.AreEqual((BigInteger)a > b, (UInt256)a > (UInt256)b);
                Assert.AreEqual((BigInteger)a >= b, (UInt256)a >= b);
                Assert.AreEqual((BigInteger)a >= b, a >= (UInt256)b);
                Assert.AreEqual((BigInteger)a >= b, (UInt256)a >= (UInt256)b);
                Assert.AreEqual((BigInteger)a == b, (UInt256)a == b);
                Assert.AreEqual((BigInteger)a == b, a == (UInt256)b);
                Assert.AreEqual((BigInteger)a == b, (UInt256)a == (UInt256)b);
                Assert.AreEqual((BigInteger)a != b, (UInt256)a != b);
                Assert.AreEqual((BigInteger)a != b, a != (UInt256)b);
                Assert.AreEqual((BigInteger)a != b, (UInt256)a != (UInt256)b);
                Assert.AreEqual((BigInteger)a * a, UInt256.Square(a));
                Assert.AreEqual(BigInteger.Abs(a), UInt256.Abs(a));
                Assert.AreEqual(BigInteger.Abs((BigInteger)a * b), UInt256.Abs((UInt256)a * b));
                Assert.AreEqual(BigInteger.Min(a, b), UInt256.Min(a, b));
                Assert.AreEqual(BigInteger.Min((BigInteger)a * n, (BigInteger)b * n), UInt256.Min((UInt256)a * n, (UInt256)b * n));
                Assert.AreEqual(BigInteger.Max(a, b), UInt256.Max(a, b));
                Assert.AreEqual(BigInteger.Max((BigInteger)a * n, (BigInteger)b * n), UInt256.Max((UInt256)a * n, (UInt256)b * n));
                for (var j = 0; j < 2; j++)
                {
                    var m         = UInt256.Abs(j == 0 ? (UInt256)a * (UInt256)b : (UInt256)n * (UInt256)n);
                    var floorsqrt = UInt256.FloorSqrt(m);
                    Assert.IsTrue((BigInteger)floorsqrt * floorsqrt <= m && (BigInteger)(floorsqrt + 1) * (floorsqrt + 1) > m);
                    var ceilingsqrt = UInt256.CeilingSqrt(m);
                    Assert.IsTrue((BigInteger)(ceilingsqrt - 1) * (ceilingsqrt - 1) < m && (BigInteger)ceilingsqrt * ceilingsqrt >= m);
                }
                for (var j = 0; j < 2; j++)
                {
                    var m         = j == 0 ? (UInt256)a * (UInt256)b : (UInt256)BigInteger.Pow((BigInteger)Math.Floor(Math.Pow((double)((BigInteger)a * b), (double)1 / 3)), 3);
                    var floorcbrt = UInt256.FloorCbrt(m);
                    Assert.IsTrue((BigInteger)floorcbrt * floorcbrt * floorcbrt <= m && (BigInteger)(floorcbrt + 1) * (floorcbrt + 1) * (floorcbrt + 1) > m);
                    var ceilingcbrt = UInt256.CeilingCbrt(m);
                    Assert.IsTrue((BigInteger)(ceilingcbrt - 1) * (ceilingcbrt - 1) * (ceilingcbrt - 1) < m && (BigInteger)ceilingcbrt * ceilingcbrt * ceilingcbrt >= m);
                }
                Assert.AreEqual(BigInteger.GreatestCommonDivisor((BigInteger)a, (BigInteger)b), UInt256.GreatestCommonDivisor((UInt256)a, (UInt256)b));
                Assert.AreEqual(BigInteger.GreatestCommonDivisor((BigInteger)a * b, (BigInteger)c * d), UInt256.GreatestCommonDivisor((UInt256)a * b, (UInt256)c * d));
                Assert.AreEqual(0, 0);
            }
        }
Пример #20
0
        public byte[]? this[byte[] key]
        {
            get
            {
                lock (_diffLock)
                {
                    RequiredPeerDifficulty = UInt256.Max(RequiredPeerDifficulty, BeamSyncContext.MinimumDifficulty.Value);
                }

                // it is not possible for the item to be requested from the DB and missing in the DB unless the DB is corrupted
                // if it is missing in the MemDb then it must exist somewhere on the web (unless the block is corrupted / invalid)

                // we grab the node from the web through requests

                // if the block is invalid then we will be timing out for a long time
                // in such case it would be good to have some gossip about corrupted blocks
                // but such gossip would be cheap
                // if we keep timing out then we would finally reject the block (but only shelve it instead of marking invalid)

                bool wasInDb = true;
                while (true)
                {
                    if (_isDisposed)
                    {
                        throw new ObjectDisposedException("Beam Sync DB disposed");
                    }

                    // shall I leave test logic forever?
                    if (BeamSyncContext.LoopIterationsToFailInTest.Value != null)
                    {
                        int?currentValue = BeamSyncContext.LoopIterationsToFailInTest.Value--;
                        if (currentValue == 0)
                        {
                            throw new Exception();
                        }
                    }

                    byte[]? fromMem = _tempDb[key] ?? _stateDb[key];
                    if (fromMem == null)
                    {
                        if (_logger.IsTrace)
                        {
                            _logger.Trace($"Beam sync miss - {key.ToHexString()} - retrieving");
                        }

                        if (BeamSyncContext.Cancelled.Value.IsCancellationRequested)
                        {
                            throw new BeamCanceledException("Beam cancellation requested");
                        }

                        if (Bytes.AreEqual(key, Keccak.Zero.Bytes))
                        {
                            // we store sync progress data at Keccak.Zero;
                            return(null);
                        }

                        TimeSpan expiry = _contextExpiryTimeSpan;
                        if (BeamSyncContext.Description.Value?.Contains("preProcess") ?? false)
                        {
                            expiry = _preProcessExpiryTimeSpan;
                        }

                        if (DateTime.UtcNow - (BeamSyncContext.LastFetchUtc.Value ?? DateTime.UtcNow) > expiry)
                        {
                            string message = $"Beam sync request {BeamSyncContext.Description.Value} for key {key.ToHexString()} with last update on {BeamSyncContext.LastFetchUtc.Value:hh:mm:ss.fff} has expired";
                            if (_logger.IsDebug)
                            {
                                _logger.Debug(message);
                            }
                            throw new BeamSyncException(message);
                        }

                        wasInDb = false;
                        // _logger.Info($"BEAM SYNC Asking for {key.ToHexString()} - resolved keys so far {_resolvedKeysCount}");

                        lock (_requestedNodes)
                        {
                            _requestedNodes.Add(new Keccak(key));
                        }

                        // _logger.Error($"Requested {key.ToHexString()}");

                        Activate();
                        _autoReset.WaitOne(50);
                    }
                    else
                    {
                        if (!wasInDb)
                        {
                            BeamSyncContext.ResolvedInContext.Value++;
                            Interlocked.Increment(ref Metrics.BeamedTrieNodes);
                            if (_logger.IsDebug)
                            {
                                _logger.Debug(
                                    $"Resolved key {key.ToHexString()} of context {BeamSyncContext.Description.Value} - resolved ctx {BeamSyncContext.ResolvedInContext.Value} | total {Metrics.BeamedTrieNodes}");
                            }
                        }
                        else
                        {
                            if (VerifiedModeEnabled &&
                                !Bytes.AreEqual(Keccak.Compute(fromMem).Bytes, key))
                            {
                                if (_logger.IsWarn)
                                {
                                    _logger.Warn($"DB had an entry with a hash mismatch {key.ToHexString()} vs {Keccak.Compute(fromMem).Bytes.ToHexString()}");
                                }
                                _tempDb[key]  = null;
                                _stateDb[key] = null;
                                continue;
                            }
                        }

                        BeamSyncContext.LastFetchUtc.Value = DateTime.UtcNow;
                        return(fromMem);
                    }
                }
            }

            set
            {
                if (_logger.IsTrace)
                {
                    _logger.Trace($"Saving to temp - {key.ToHexString()}");
                }
                _targetDbForSaves[key] = value;
            }
        }
Пример #21
0
        public byte[] this[byte[] key]
        {
            get
            {
                lock (_diffLock)
                {
                    RequiredPeerDifficulty = UInt256.Max(RequiredPeerDifficulty, BeamSyncContext.MinimumDifficulty.Value);
                }

                // it is not possible for the item to be requested from the DB and missing in the DB unless the DB is corrupted
                // if it is missing in the MemDb then it must exist somewhere on the web (unless the block is corrupted / invalid)

                // we grab the node from the web through requests

                // if the block is invalid then we will be timing out for a long time
                // in such case it would be good to have some gossip about corrupted blocks
                // but such gossip would be cheap
                // if we keep timing out then we would finally reject the block (but only shelve it instead of marking invalid)

                bool wasInDb = true;
                while (true)
                {
                    if (BeamSyncContext.Cancelled.Value.IsCancellationRequested)
                    {
                        throw new TaskCanceledException("Beam Sync task cancelled by a new block.");
                    }

                    if (_isDisposed)
                    {
                        throw new ObjectDisposedException("Beam Sync DB disposed");
                    }

                    // shall I leave test logic forever?
                    if (BeamSyncContext.LoopIterationsToFailInTest.Value != null)
                    {
                        int?currentValue = BeamSyncContext.LoopIterationsToFailInTest.Value--;
                        if (currentValue == 0)
                        {
                            throw new Exception();
                        }
                    }

                    var fromMem = _db[key];
                    if (fromMem == null)
                    {
                        if (Bytes.AreEqual(key, Keccak.Zero.Bytes))
                        {
                            // we store sync progress data at Keccak.Zero;
                            return(null);
                        }

                        TimeSpan expiry = _contextExpiryTimeSpan;
                        if (BeamSyncContext.Description.Value?.Contains("preProcess") ?? false)
                        {
                            expiry = _preProcessExpiryTimeSpan;
                        }

                        if (DateTime.UtcNow - (BeamSyncContext.LastFetchUtc.Value ?? DateTime.UtcNow) > expiry)
                        {
                            string message = $"Beam sync request {BeamSyncContext.Description.Value} with last update on {BeamSyncContext.LastFetchUtc.Value:hh:mm:ss.fff} has expired";
                            if (_logger.IsDebug)
                            {
                                _logger.Debug(message);
                            }
                            throw new BeamSyncException(message);
                        }

                        wasInDb = false;
                        // _logger.Info($"BEAM SYNC Asking for {key.ToHexString()} - resolved keys so far {_resolvedKeysCount}");

                        int count;
                        lock (_requestedNodes)
                        {
                            _requestedNodes.Add(new Keccak(key));
                            count = _requestedNodes.Count;
                        }

                        // _logger.Error($"Requested {key.ToHexString()}");

                        NeedMoreData?.Invoke(this, EventArgs.Empty);

                        _autoReset.WaitOne(50);
                    }
                    else
                    {
                        if (!wasInDb)
                        {
                            BeamSyncContext.ResolvedInContext.Value++;
                            Interlocked.Increment(ref _resolvedKeysCount);
                            // if (_logger.IsInfo) _logger.Info($"{_description} Resolved key {key.ToHexString()} of context {BeamSyncContext.Description.Value} - resolved ctx {BeamSyncContext.ResolvedInContext.Value} | total {_resolvedKeysCount}");
                        }

                        BeamSyncContext.LastFetchUtc.Value = DateTime.UtcNow;
                        return(fromMem);
                    }
                }
            }

            set => _db[key] = value;