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)); }
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); }
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); }
private static Keccak GetTruncatedHash(BlockHeader header) { Keccak headerHashed = Keccak.Compute(Rlp.Encode(header, RlpBehaviors.ExcludeBlockMixHashAndNonce)); // sic! Keccak here not Keccak512 return(headerHashed); }
public Account WithChangedCodeHash(Keccak newCodeHash) { return(new Account(Nonce, Balance, StorageRoot, newCodeHash, IsTotallyEmpty && newCodeHash == Keccak.OfAnEmptyString)); }
public void VisitCode(Keccak codeHash, byte[] code, VisitContext visitContext) { _builder.AppendLine($"{GetPrefix(visitContext)}CODE {codeHash} LENGTH {code.Length}"); }
public bool ShouldVisit(Keccak nextNode) { return(true); }
public bool IsPersisted(Keccak keccak) => _trieStore.IsPersisted(keccak);
public byte[] LoadRlp(Keccak hash) => _trieStore.LoadRlp(hash, _readOnlyStore);
public TrieNode FindCachedOrUnknown(Keccak hash) => _trieStore.FindCachedOrUnknown(hash, true);
public static Keccak Calculate(BlockHeader[] ommers) { return(ommers.Length == 0 ? Keccak.OfAnEmptySequenceRlp : Keccak.Compute(Rlp.Encode(ommers).Bytes)); }
public BlockParameter(Keccak blockHash, bool requireCanonical) { Type = BlockParameterType.BlockHash; BlockHash = blockHash; RequireCanonical = requireCanonical; }
public BlockParameter(Keccak blockHash) { Type = BlockParameterType.BlockHash; BlockHash = blockHash; }
public bool IsMainChain(Keccak blockHash) => _headBlock.Hash == blockHash;
public Signature Sign(Address address, Keccak message) { return(_wallet.Sign(message, address)); }
public Keccak GetBlockHash(Keccak transactionHash) => _receiptStorage.Find(transactionHash).BlockHash;
public void VisitMissingNode(Keccak nodeHash, VisitContext visitContext) { _builder.AppendLine($"{GetIndent(visitContext.Level) }{GetChildIndex(visitContext)}MISSING {nodeHash}"); }
public byte[] GetCode(Keccak codeHash) { return(_stateReader.GetCode(codeHash)); }
public Account WithChangedStorageRoot(Keccak newStorageRoot) { return(new Account(Nonce, Balance, newStorageRoot, CodeHash, IsTotallyEmpty && newStorageRoot == Keccak.EmptyTreeHash)); }
private UInt256 GetNonce(Keccak stateRoot, Address address) { return(_stateReader.GetNonce(stateRoot, address)); }
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)}"); } } }
public byte[] GetStorage(Address address, UInt256 index, Keccak stateRoot) { _stateProvider.StateRoot = stateRoot; return(_storageProvider.Get(new StorageAddress(address, index))); }
Task <bool> IBlockTreeVisitor.VisitMissing(Keccak hash, CancellationToken cancellationToken) { throw new InvalidDataException($"Block {hash} is missing from the database when loading blocks."); }
public Account GetAccount(Address address, Keccak stateRoot) { return(_stateReader.GetAccount(stateRoot, address)); }
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 }
public void RunTreeVisitor(ITreeVisitor treeVisitor, Keccak stateRoot) { _stateReader.RunTreeVisitor(stateRoot, treeVisitor); }
public void SetClaimedRefundTransactionHash(Keccak transactionHash) { ClaimedRefundTransactionHash = transactionHash; }
public Block FindBlock(Keccak blockHash) => _blockFinder.FindBlock(blockHash);
public BlockHeader FindHeader(Keccak blockHash) => _blockFinder.FindHeader(blockHash);
public BlockHeader FindHeader(Keccak blockHash, BlockTreeLookupOptions options) => _headBlock.Hash == blockHash ? _headBlock.Header : null;