private static BlockHeader Convert(TestBlockHeaderJson headerJson) { if (headerJson == null) { return(null); } BlockHeader header = new BlockHeader( new Keccak(headerJson.ParentHash), new Keccak(headerJson.UncleHash), new Address(headerJson.Coinbase), Bytes.FromHexString(headerJson.Difficulty).ToUInt256(), Bytes.FromHexString(headerJson.Number).ToUInt256(), (long)Bytes.FromHexString(headerJson.GasLimit).ToUnsignedBigInteger(), Bytes.FromHexString(headerJson.Timestamp).ToUInt256(), Bytes.FromHexString(headerJson.ExtraData) ); header.Bloom = new Bloom(Bytes.FromHexString(headerJson.Bloom).ToBigEndianBitArray2048()); header.GasUsed = (long)Bytes.FromHexString(headerJson.GasUsed).ToUnsignedBigInteger(); header.Hash = new Keccak(headerJson.Hash); header.MixHash = new Keccak(headerJson.MixHash); header.Nonce = (ulong)Bytes.FromHexString(headerJson.Nonce).ToUnsignedBigInteger(); header.ReceiptsRoot = new Keccak(headerJson.ReceiptTrie); header.StateRoot = new Keccak(headerJson.StateRoot); header.TransactionsRoot = new Keccak(headerJson.TransactionsTrie); return(header); }
private List <string> RunAssertions(LegacyBlockchainTest test, Block headBlock, IStorageProvider storageProvider, IStateProvider stateProvider) { if (test.PostStateRoot != null) { return(test.PostStateRoot != stateProvider.StateRoot ? new List <string> { "state root mismatch" } : Enumerable.Empty <string>().ToList()); } TestBlockHeaderJson testHeaderJson = test.Blocks .Where(b => b.BlockHeader != null) .SingleOrDefault(b => new Keccak(b.BlockHeader.Hash) == headBlock.Hash)?.BlockHeader ?? test.GenesisBlockHeader; BlockHeader testHeader = JsonToBlockchainTest.Convert(testHeaderJson); List <string> differences = new List <string>(); var deletedAccounts = test.Pre.Where(pre => !test.PostState.ContainsKey(pre.Key)); foreach (KeyValuePair <Address, AccountState> deletedAccount in deletedAccounts) { if (stateProvider.AccountExists(deletedAccount.Key)) { differences.Add($"Pre state account {deletedAccount.Key} was not deleted as expected."); } } foreach (KeyValuePair <Address, AccountState> accountState in test.PostState) { int differencesBefore = differences.Count; if (differences.Count > 8) { Console.WriteLine("More than 8 differences..."); break; } bool accountExists = stateProvider.AccountExists(accountState.Key); BigInteger?balance = accountExists ? stateProvider.GetBalance(accountState.Key) : (BigInteger?)null; BigInteger?nonce = accountExists ? stateProvider.GetNonce(accountState.Key) : (BigInteger?)null; if (accountState.Value.Balance != balance) { differences.Add($"{accountState.Key} balance exp: {accountState.Value.Balance}, actual: {balance}, diff: {balance - accountState.Value.Balance}"); } if (accountState.Value.Nonce != nonce) { differences.Add($"{accountState.Key} nonce exp: {accountState.Value.Nonce}, actual: {nonce}"); } byte[] code = accountExists ? stateProvider.GetCode(accountState.Key) : new byte[0]; if (!Bytes.AreEqual(accountState.Value.Code, code)) { differences.Add($"{accountState.Key} code exp: {accountState.Value.Code?.Length}, actual: {code?.Length}"); } if (differences.Count != differencesBefore) { _logger.Info($"ACCOUNT STATE ({accountState.Key}) HAS DIFFERENCES"); } differencesBefore = differences.Count; KeyValuePair <UInt256, byte[]>[] clearedStorages = new KeyValuePair <UInt256, byte[]> [0]; if (test.Pre.ContainsKey(accountState.Key)) { clearedStorages = test.Pre[accountState.Key].Storage.Where(s => !accountState.Value.Storage.ContainsKey(s.Key)).ToArray(); } foreach (KeyValuePair <UInt256, byte[]> clearedStorage in clearedStorages) { byte[] value = !stateProvider.AccountExists(accountState.Key) ? Bytes.Empty : storageProvider.Get(new StorageAddress(accountState.Key, clearedStorage.Key)); if (!value.IsZero()) { differences.Add($"{accountState.Key} storage[{clearedStorage.Key}] exp: 0x00, actual: {value.ToHexString(true)}"); } } foreach (KeyValuePair <UInt256, byte[]> storageItem in accountState.Value.Storage) { byte[] value = !stateProvider.AccountExists(accountState.Key) ? Bytes.Empty : storageProvider.Get(new StorageAddress(accountState.Key, storageItem.Key)) ?? new byte[0]; if (!Bytes.AreEqual(storageItem.Value, value)) { differences.Add($"{accountState.Key} storage[{storageItem.Key}] exp: {storageItem.Value.ToHexString(true)}, actual: {value.ToHexString(true)}"); } } if (differences.Count != differencesBefore) { _logger.Info($"ACCOUNT STORAGE ({accountState.Key}) HAS DIFFERENCES"); } } BigInteger gasUsed = headBlock.Header.GasUsed; if ((testHeader?.GasUsed ?? 0) != gasUsed) { differences.Add($"GAS USED exp: {testHeader?.GasUsed ?? 0}, actual: {gasUsed}"); } if (headBlock.Transactions.Any() && testHeader.Bloom.ToString() != headBlock.Header.Bloom.ToString()) { differences.Add($"BLOOM exp: {testHeader.Bloom}, actual: {headBlock.Header.Bloom}"); } if (testHeader.StateRoot != stateProvider.StateRoot) { differences.Add($"STATE ROOT exp: {testHeader.StateRoot}, actual: {stateProvider.StateRoot}"); } if (testHeader.TxRoot != headBlock.Header.TxRoot) { differences.Add($"TRANSACTIONS ROOT exp: {testHeader.TxRoot}, actual: {headBlock.Header.TxRoot}"); } if (testHeader.ReceiptsRoot != headBlock.Header.ReceiptsRoot) { differences.Add($"RECEIPT ROOT exp: {testHeader.ReceiptsRoot}, actual: {headBlock.Header.ReceiptsRoot}"); } if (test.LastBlockHash != headBlock.Hash) { differences.Add($"LAST BLOCK HASH exp: {test.LastBlockHash}, actual: {headBlock.Hash}"); } foreach (string difference in differences) { _logger.Info(difference); } return(differences); }
private void RunAssertions(BlockchainTest test, Block headBlock, IStorageProvider storageProvider, IStateProvider stateProvider) { TestBlockHeaderJson testHeaderJson = test.Blocks .Where(b => b.BlockHeader != null) .SingleOrDefault(b => new Keccak(b.BlockHeader.Hash) == headBlock.Hash)?.BlockHeader ?? test.GenesisBlockHeader; BlockHeader testHeader = Convert(testHeaderJson); List <string> differences = new List <string>(); foreach (KeyValuePair <Address, AccountState> accountState in test.PostState) { int differencesBefore = differences.Count; if (differences.Count > 8) { Console.WriteLine("More than 8 differences..."); break; } bool accountExists = stateProvider.AccountExists(accountState.Key); BigInteger?balance = accountExists ? stateProvider.GetBalance(accountState.Key) : (BigInteger?)null; BigInteger?nonce = accountExists ? stateProvider.GetNonce(accountState.Key) : (BigInteger?)null; if (accountState.Value.Balance != balance) { differences.Add($"{accountState.Key} balance exp: {accountState.Value.Balance}, actual: {balance}, diff: {balance - accountState.Value.Balance}"); } if (accountState.Value.Nonce != nonce) { differences.Add($"{accountState.Key} nonce exp: {accountState.Value.Nonce}, actual: {nonce}"); } byte[] code = accountExists ? stateProvider.GetCode(accountState.Key) : new byte[0]; if (!Bytes.UnsafeCompare(accountState.Value.Code, code)) { differences.Add($"{accountState.Key} code exp: {accountState.Value.Code?.Length}, actual: {code?.Length}"); } if (differences.Count != differencesBefore) { _logger.Info($"ACCOUNT STATE ({accountState.Key}) HAS DIFFERENCES"); } differencesBefore = differences.Count; foreach (KeyValuePair <BigInteger, byte[]> storageItem in accountState.Value.Storage) { byte[] value = storageProvider.Get(new StorageAddress(accountState.Key, storageItem.Key)) ?? new byte[0]; if (!Bytes.UnsafeCompare(storageItem.Value, value)) { differences.Add($"{accountState.Key} storage[{storageItem.Key}] exp: {Hex.FromBytes(storageItem.Value, true)}, actual: {Hex.FromBytes(value, true)}"); } } if (differences.Count != differencesBefore) { _logger.Info($"ACCOUNT STORAGE ({accountState.Key}) HAS DIFFERENCES"); } } BigInteger gasUsed = headBlock.Header.GasUsed; if ((testHeader?.GasUsed ?? 0) != gasUsed) { differences.Add($"GAS USED exp: {testHeader?.GasUsed ?? 0}, actual: {gasUsed}"); } if (headBlock.Transactions.Any() && testHeader.Bloom.ToString() != headBlock.Header.Bloom.ToString()) { differences.Add($"BLOOM exp: {testHeader.Bloom}, actual: {headBlock.Header.Bloom}"); } if (testHeader.StateRoot != stateProvider.StateRoot) { differences.Add($"STATE ROOT exp: {testHeader.StateRoot}, actual: {stateProvider.StateRoot}"); } if (testHeader.TransactionsRoot != headBlock.Header.TransactionsRoot) { differences.Add($"TRANSACTIONS ROOT exp: {testHeader.TransactionsRoot}, actual: {headBlock.Header.TransactionsRoot}"); } if (testHeader.ReceiptsRoot != headBlock.Header.ReceiptsRoot) { differences.Add($"RECEIPT ROOT exp: {testHeader.ReceiptsRoot}, actual: {headBlock.Header.ReceiptsRoot}"); } if (test.LastBlockHash != headBlock.Hash) { differences.Add($"LAST BLOCK HASH exp: {test.LastBlockHash}, actual: {headBlock.Hash}"); } foreach (string difference in differences) { _logger.Info(difference); } Assert.Zero(differences.Count, "differences"); }