Exemplo n.º 1
2
        public async Task<BlobFingerprint> GetFingerprintAsync(Stream stream, CancellationToken cancellationToken)
        {
            using (var sha3 = new Keccak())
            using (var sha256 = SHA256.Create())
            using (var md5 = MD5.Create())
            {
                var buffers = new[] { AllocateBuffer(), AllocateBuffer() };
                var index = 0;

                var totalLength = 0L;

                var readTask = stream.ReadAsync(buffers[index], 0, buffers[index].Length, cancellationToken);

                for (;;)
                {
                    var length = await readTask.ConfigureAwait(false);

                    if (length < 1)
                        break;

                    var buffer = buffers[index];

                    if (++index >= buffers.Length)
                        index = 0;

                    readTask = stream.ReadAsync(buffers[index], 0, buffers[index].Length, cancellationToken);

                    totalLength += length;

                    sha3.TransformBlock(buffer, 0, length, null, 0);

                    sha256.TransformBlock(buffer, 0, length, null, 0);

                    md5.TransformBlock(buffer, 0, length, null, 0);
                }

                sha3.TransformFinalBlock(buffers[0], 0, 0);

                sha256.TransformFinalBlock(buffers[0], 0, 0);

                md5.TransformFinalBlock(buffers[0], 0, 0);

                foreach (var buffer in buffers)
                    FreeBuffer(buffer);

                var fingerprint = new BlobFingerprint(totalLength, sha3.Hash, sha256.Hash, md5.Hash);

                return fingerprint;
            }
        }
        public Keccak FindBlockHash(Keccak txHash)
        {
            var blockHashData = _transactionDb.Get(txHash);

            return(blockHashData == null?FindReceiptObsolete(txHash)?.BlockHash : new Keccak(blockHashData));
        }
Exemplo n.º 3
0
        public void Setup()
        {
            _blockTree = Substitute.For <IBlockTree>();
            _headStep  = 10;
            _blockTree.Head.Returns(Build.A.Block.WithHeader(Build.A.BlockHeader.WithHash(Keccak.Compute("hash")).WithAura(_headStep, Array.Empty <byte>()).TestObject).TestObject);

            _auRaStepCalculator  = Substitute.For <IAuRaStepCalculator>();
            _validatorStore      = Substitute.For <IValidatorStore>();
            _validSealerStrategy = Substitute.For <IValidSealerStrategy>();
            Signer signer = new(ChainId.Mainnet, Build.A.PrivateKey.TestObject, LimboLogs.Instance);

            _address = signer.Address;

            _auRaSealer = new AuRaSealer(
                _blockTree,
                _validatorStore,
                _auRaStepCalculator,
                signer,
                _validSealerStrategy,
                LimboLogs.Instance);
        }
Exemplo n.º 4
0
        private Block PrepareBlock(Block parentBlock)
        {
            BlockHeader parentHeader = parentBlock.Header;

            if (parentHeader == null)
            {
                if (_logger.IsError)
                {
                    _logger.Error($"Preparing new block on top of {parentBlock.ToString(Block.Format.Short)} - parent header is null");
                }
                return(null);
            }

            if (_recentNotAllowedParent == parentBlock.Hash)
            {
                return(null);
            }

            if (!_sealer.CanSeal(parentHeader.Number + 1, parentHeader.Hash))
            {
                if (_logger.IsTrace)
                {
                    _logger.Trace($"Not allowed to sign block ({parentBlock.Number + 1})");
                }
                _recentNotAllowedParent = parentHeader.Hash;
                return(null);
            }

            if (_logger.IsInfo)
            {
                _logger.Info($"Preparing new block on top of {parentBlock.ToString(Block.Format.Short)}");
            }

            UInt256 timestamp = _timestamp.EpochSeconds;

            BlockHeader header = new BlockHeader(
                parentBlock.Hash,
                Keccak.OfAnEmptySequenceRlp,
                Address.Zero,
                1,
                parentBlock.Number + 1,
                parentBlock.GasLimit,
                timestamp > parentBlock.Timestamp ? timestamp : parentBlock.Timestamp + 1,
                new byte[0]);

            // If the block isn't a checkpoint, cast a random vote (good enough for now)
            long number = header.Number;
            // Assemble the voting snapshot to check which votes make sense
            Snapshot snapshot     = _snapshotManager.GetOrCreateSnapshot(number - 1, header.ParentHash);
            bool     isEpochBlock = (ulong)number % 30000 == 0;

            if (!isEpochBlock && _proposals.Any())
            {
                // Gather all the proposals that make sense voting on
                List <Address> addresses = new List <Address>();
                foreach (var proposal in _proposals)
                {
                    Address address   = proposal.Key;
                    bool    authorize = proposal.Value;
                    if (_snapshotManager.IsValidVote(snapshot, address, authorize))
                    {
                        addresses.Add(address);
                    }
                }

                // If there's pending proposals, cast a vote on them
                if (addresses.Count > 0)
                {
                    header.Beneficiary = addresses[_cryptoRandom.NextInt(addresses.Count)];
                    header.Nonce       = _proposals[header.Beneficiary] ? Clique.NonceAuthVote : Clique.NonceDropVote;
                }
            }

            // Set the correct difficulty
            header.Difficulty      = CalculateDifficulty(snapshot, _address);
            header.TotalDifficulty = parentBlock.TotalDifficulty + header.Difficulty;
            if (_logger.IsDebug)
            {
                _logger.Debug($"Setting total difficulty to {parentBlock.TotalDifficulty} + {header.Difficulty}.");
            }

            // Set extra data
            int mainBytesLength   = Clique.ExtraVanityLength + Clique.ExtraSealLength;
            int signerBytesLength = isEpochBlock ? 20 * snapshot.Signers.Count : 0;
            int extraDataLength   = mainBytesLength + signerBytesLength;

            header.ExtraData = new byte[extraDataLength];

            byte[] clientName = Encoding.UTF8.GetBytes("Nethermind");
            Array.Copy(clientName, header.ExtraData, clientName.Length);

            if (isEpochBlock)
            {
                for (int i = 0; i < snapshot.Signers.Keys.Count; i++)
                {
                    Address signer = snapshot.Signers.Keys[i];
                    int     index  = Clique.ExtraVanityLength + 20 * i;
                    Array.Copy(signer.Bytes, 0, header.ExtraData, index, signer.Bytes.Length);
                }
            }

            // Mix digest is reserved for now, set to empty
            header.MixHash = Keccak.Zero;
            // Ensure the timestamp has the correct delay
            header.Timestamp = parentBlock.Timestamp + _config.BlockPeriod;
            if (header.Timestamp < _timestamp.EpochSeconds)
            {
                header.Timestamp = new UInt256(_timestamp.EpochSeconds);
            }

            var transactions = _txPool.GetPendingTransactions().OrderBy(t => t.Nonce).ThenByDescending(t => t.GasPrice).ThenBy(t => t.GasLimit); // by nonce in case there are two transactions for the same account

            var        selectedTxs  = new List <Transaction>();
            BigInteger gasRemaining = header.GasLimit;

            if (_logger.IsDebug)
            {
                _logger.Debug($"Collecting pending transactions at min gas price {MinGasPriceForMining} and block gas limit {gasRemaining}.");
            }

            int total = 0;

            _stateProvider.StateRoot = parentHeader.StateRoot;

            Dictionary <Address, UInt256> nonces = new Dictionary <Address, UInt256>();

            foreach (Transaction transaction in transactions)
            {
                total++;
                if (transaction.SenderAddress == null)
                {
                    if (_logger.IsError)
                    {
                        _logger.Error("Rejecting null sender pending transaction.");
                    }
                    continue;
                }

                if (transaction.GasPrice < MinGasPriceForMining)
                {
                    if (_logger.IsTrace)
                    {
                        _logger.Trace($"Rejecting transaction - gas price ({transaction.GasPrice}) too low (min gas price: {MinGasPriceForMining}.");
                    }
                    continue;
                }

                if (transaction.Nonce != _stateProvider.GetNonce(transaction.SenderAddress) && (!nonces.ContainsKey(transaction.SenderAddress) || nonces[transaction.SenderAddress] + 1 != transaction.Nonce))
                {
                    if (_logger.IsTrace)
                    {
                        _logger.Trace($"Rejecting transaction based on nonce.");
                    }
                    continue;
                }

                if (transaction.GasLimit > gasRemaining)
                {
                    if (_logger.IsTrace)
                    {
                        _logger.Trace($"Rejecting transaction - gas limit ({transaction.GasPrice}) more than remaining gas ({gasRemaining}).");
                    }
                    continue;
                }

                BigInteger requiredBalance = transaction.GasLimit * (BigInteger)transaction.GasPrice + transaction.Value;
                BigInteger balance         = _stateProvider.GetBalance(transaction.SenderAddress);
                if (requiredBalance > balance)
                {
                    if (_logger.IsTrace)
                    {
                        _logger.Trace($"Rejecting transaction - insufficient balance - required {requiredBalance}, actual {balance}.");
                    }
                    continue;
                }

                selectedTxs.Add(transaction);
                nonces[transaction.SenderAddress] = transaction.Nonce;
                gasRemaining -= transaction.GasLimit;
            }

            if (_logger.IsDebug)
            {
                _logger.Debug($"Collected {selectedTxs.Count} out of {total} pending transactions.");
            }

            Block block = new Block(header, selectedTxs, new BlockHeader[0]);

            header.TxRoot = block.CalculateTxRoot();
            block.Author  = _address;
            return(block);
        }
Exemplo n.º 5
0
        private static Keccak GetTruncatedHash(BlockHeader header)
        {
            Keccak headerHashed = Keccak.Compute(Rlp.Encode(header, RlpBehaviors.ExcludeBlockMixHashAndNonce)); // sic! Keccak here not Keccak512

            return(headerHashed);
        }
Exemplo n.º 6
0
 public Account WithChangedCodeHash(Keccak newCodeHash)
 {
     return(new Account(Nonce, Balance, StorageRoot, newCodeHash, IsTotallyEmpty && newCodeHash == Keccak.OfAnEmptyString));
 }
Exemplo n.º 7
0
 public void VisitCode(Keccak codeHash, byte[] code, VisitContext visitContext)
 {
     _builder.AppendLine($"{GetPrefix(visitContext)}CODE {codeHash} LENGTH {code.Length}");
 }
Exemplo n.º 8
0
 public bool ShouldVisit(Keccak nextNode)
 {
     return(true);
 }
Exemplo n.º 9
0
 public bool IsPersisted(Keccak keccak) => _trieStore.IsPersisted(keccak);
Exemplo n.º 10
0
 public byte[] LoadRlp(Keccak hash) => _trieStore.LoadRlp(hash, _readOnlyStore);
Exemplo n.º 11
0
 public TrieNode FindCachedOrUnknown(Keccak hash) =>
 _trieStore.FindCachedOrUnknown(hash, true);
Exemplo n.º 12
0
 public static Keccak Calculate(BlockHeader[] ommers)
 {
     return(ommers.Length == 0
         ? Keccak.OfAnEmptySequenceRlp
         : Keccak.Compute(Rlp.Encode(ommers).Bytes));
 }
Exemplo n.º 13
0
 public BlockParameter(Keccak blockHash, bool requireCanonical)
 {
     Type             = BlockParameterType.BlockHash;
     BlockHash        = blockHash;
     RequireCanonical = requireCanonical;
 }
Exemplo n.º 14
0
 public BlockParameter(Keccak blockHash)
 {
     Type      = BlockParameterType.BlockHash;
     BlockHash = blockHash;
 }
 public bool IsMainChain(Keccak blockHash) => _headBlock.Hash == blockHash;
Exemplo n.º 16
0
 public Signature Sign(Address address, Keccak message)
 {
     return(_wallet.Sign(message, address));
 }
Exemplo n.º 17
0
 public Keccak GetBlockHash(Keccak transactionHash) => _receiptStorage.Find(transactionHash).BlockHash;
Exemplo n.º 18
0
 public void VisitMissingNode(Keccak nodeHash, VisitContext visitContext)
 {
     _builder.AppendLine($"{GetIndent(visitContext.Level) }{GetChildIndex(visitContext)}MISSING {nodeHash}");
 }
Exemplo n.º 19
0
 public byte[] GetCode(Keccak codeHash)
 {
     return(_stateReader.GetCode(codeHash));
 }
Exemplo n.º 20
0
 public Account WithChangedStorageRoot(Keccak newStorageRoot)
 {
     return(new Account(Nonce, Balance, newStorageRoot, CodeHash, IsTotallyEmpty && newStorageRoot == Keccak.EmptyTreeHash));
 }
Exemplo n.º 21
0
 private UInt256 GetNonce(Keccak stateRoot, Address address)
 {
     return(_stateReader.GetNonce(stateRoot, address));
 }
Exemplo n.º 22
0
        protected void RunTest(VirtualMachineTest test)
        {
            TestContext.WriteLine($"Running {test.GetType().FullName}");

            VirtualMachine       machine     = new VirtualMachine(_stateProvider, _storageProvider, _blockhashProvider, _logManager);
            ExecutionEnvironment environment = new ExecutionEnvironment();

            environment.Value            = test.Execution.Value;
            environment.CallDepth        = 0;
            environment.Sender           = test.Execution.Caller;
            environment.ExecutingAccount = test.Execution.Address;


            BlockHeader header = new BlockHeader(
                Keccak.OfAnEmptyString,
                Keccak.OfAnEmptySequenceRlp,
                test.Environment.CurrentCoinbase,
                test.Environment.CurrentDifficulty,
                test.Environment.CurrentNumber,
                (long)test.Environment.CurrentGasLimit,
                test.Environment.CurrentTimestamp, Bytes.Empty);

            environment.CurrentBlock = header;

            environment.GasPrice   = test.Execution.GasPrice;
            environment.InputData  = test.Execution.Data;
            environment.CodeInfo   = new CodeInfo(test.Execution.Code);
            environment.Originator = test.Execution.Origin;

            foreach (KeyValuePair <Address, AccountState> accountState in test.Pre)
            {
                foreach (KeyValuePair <UInt256, byte[]> storageItem in accountState.Value.Storage)
                {
                    _storageProvider.Set(new StorageAddress(accountState.Key, storageItem.Key), storageItem.Value);
                    if (accountState.Key.Equals(test.Execution.Address))
                    {
                        _storageProvider.Set(new StorageAddress(accountState.Key, storageItem.Key), storageItem.Value);
                    }
                }

                _stateProvider.UpdateCode(accountState.Value.Code);

                _stateProvider.CreateAccount(accountState.Key, accountState.Value.Balance);
                Keccak codeHash = _stateProvider.UpdateCode(accountState.Value.Code);
                _stateProvider.UpdateCodeHash(accountState.Key, codeHash, Olympic.Instance);
                for (int i = 0; i < accountState.Value.Nonce; i++)
                {
                    _stateProvider.IncrementNonce(accountState.Key);
                }
            }

            EvmState state = new EvmState((long)test.Execution.Gas, environment, ExecutionType.Transaction, false, true, false);

            _storageProvider.Commit();
            _stateProvider.Commit(Olympic.Instance);

            TransactionSubstate substate = machine.Run(state, Olympic.Instance, NullTxTracer.Instance);

            if (test.Out == null)
            {
                Assert.NotNull(substate.Error);
                return;
            }

            Assert.True(Bytes.AreEqual(test.Out, substate.Output),
                        $"Exp: {test.Out.ToHexString(true)} != Actual: {substate.Output.ToHexString(true)}");
            Assert.AreEqual((long)test.Gas, state.GasAvailable);
            foreach (KeyValuePair <Address, AccountState> accountState in test.Post)
            {
                bool    accountExists = _stateProvider.AccountExists(accountState.Key);
                UInt256 balance       = accountExists ? _stateProvider.GetBalance(accountState.Key) : 0;
                UInt256 nonce         = accountExists ? _stateProvider.GetNonce(accountState.Key) : 0;
                Assert.AreEqual(accountState.Value.Balance, balance, $"{accountState.Key} Balance");
                Assert.AreEqual(accountState.Value.Nonce, nonce, $"{accountState.Key} Nonce");

                // TODO: not testing properly 0 balance accounts
                if (accountExists)
                {
                    byte[] code = _stateProvider.GetCode(accountState.Key);
                    Assert.AreEqual(accountState.Value.Code, code, $"{accountState.Key} Code");
                }

                foreach (KeyValuePair <UInt256, byte[]> storageItem in accountState.Value.Storage)
                {
                    byte[] value = _storageProvider.Get(new StorageAddress(accountState.Key, storageItem.Key));
                    Assert.True(Bytes.AreEqual(storageItem.Value, value),
                                $"Storage[{accountState.Key}_{storageItem.Key}] Exp: {storageItem.Value.ToHexString(true)} != Actual: {value.ToHexString(true)}");
                }
            }
        }
Exemplo n.º 23
0
 public byte[] GetStorage(Address address, UInt256 index, Keccak stateRoot)
 {
     _stateProvider.StateRoot = stateRoot;
     return(_storageProvider.Get(new StorageAddress(address, index)));
 }
Exemplo n.º 24
0
 Task <bool> IBlockTreeVisitor.VisitMissing(Keccak hash, CancellationToken cancellationToken)
 {
     throw new InvalidDataException($"Block {hash} is missing from the database when loading blocks.");
 }
Exemplo n.º 25
0
 public Account GetAccount(Address address, Keccak stateRoot)
 {
     return(_stateReader.GetAccount(stateRoot, address));
 }
Exemplo n.º 26
0
        public (byte[], byte[], bool) Hashimoto(ulong fullSize, IEthashDataSet dataSet, Keccak headerHash, Keccak expectedMixHash, ulong nonce)
        {
            uint       hashesInFull = (uint)(fullSize / HashBytes); // TODO: at current rate would cover around 200 years... but will the block rate change? what with private chains with shorter block times?
            const uint wordsInMix   = MixBytes / WordBytes;
            const uint hashesInMix  = MixBytes / HashBytes;

            byte[] nonceBytes = new byte[8];
            BinaryPrimitives.WriteUInt64LittleEndian(nonceBytes, nonce);

            byte[] headerAndNonceHashed = Keccak512.Compute(Bytes.Concat(headerHash.Bytes, nonceBytes)).Bytes; // this tests fine
            uint[] mixInts = new uint[MixBytes / WordBytes];

            for (int i = 0; i < hashesInMix; i++)
            {
                Buffer.BlockCopy(headerAndNonceHashed, 0, mixInts, i * headerAndNonceHashed.Length, headerAndNonceHashed.Length);
            }

            uint firstOfHeaderAndNonce = GetUInt(headerAndNonceHashed, 0);

            for (uint i = 0; i < Accesses; i++)
            {
                uint   p       = Fnv(i ^ firstOfHeaderAndNonce, mixInts[i % wordsInMix]) % (hashesInFull / hashesInMix) * hashesInMix; // since we take 'hashesInMix' consecutive blocks we want only starting indices of such blocks
                uint[] newData = new uint[wordsInMix];
                for (uint j = 0; j < hashesInMix; j++)
                {
                    uint[] item = dataSet.CalcDataSetItem(p + j);
                    Buffer.BlockCopy(item, 0, newData, (int)(j * item.Length * 4), item.Length * 4);
                }

                Fnv(mixInts, newData);
            }

            uint[] cmixInts = new uint[MixBytes / WordBytes / 4];
            for (uint i = 0; i < mixInts.Length; i += 4)
            {
                cmixInts[i / 4] = Fnv(Fnv(Fnv(mixInts[i], mixInts[i + 1]), mixInts[i + 2]), mixInts[i + 3]);
            }

            byte[] cmix = new byte[MixBytes / WordBytes];
            Buffer.BlockCopy(cmixInts, 0, cmix, 0, cmix.Length);

            if (expectedMixHash != null && !Bytes.AreEqual(cmix, expectedMixHash.Bytes))
            {
                return(null, null, false);
            }

            return(cmix, Keccak.Compute(Bytes.Concat(headerAndNonceHashed, cmix)).Bytes, true);  // this tests fine
        }
Exemplo n.º 27
0
 public void RunTreeVisitor(ITreeVisitor treeVisitor, Keccak stateRoot)
 {
     _stateReader.RunTreeVisitor(stateRoot, treeVisitor);
 }
Exemplo n.º 28
0
 public void SetClaimedRefundTransactionHash(Keccak transactionHash)
 {
     ClaimedRefundTransactionHash = transactionHash;
 }
Exemplo n.º 29
0
 public Block FindBlock(Keccak blockHash) => _blockFinder.FindBlock(blockHash);
Exemplo n.º 30
0
 public BlockHeader FindHeader(Keccak blockHash) => _blockFinder.FindHeader(blockHash);
 public BlockHeader FindHeader(Keccak blockHash, BlockTreeLookupOptions options) => _headBlock.Hash == blockHash ? _headBlock.Header : null;