public Entity(uint256 txId) { if(txId == null) throw new ArgumentNullException("txId"); Timestamp = DateTimeOffset.UtcNow; TxId = txId; }
/// <summary> /// Gets a transaction. /// </summary> /// <param name="txId">The transaction identifier.</param> /// <returns>Given a transaction hash (id) returns the requested transaction object.</returns> /// <exception cref="System.ArgumentNullException">txId cannot be null</exception> public async Task<Transaction> GetTransactionAsync(uint256 txId) { if (txId == null) throw new ArgumentNullException("txId"); var result = await SendRequestAsync("tx", _format, txId.ToString()); return new Transaction(result); }
public uint256_tests() { R1Array = ToBytes("\x9c\x52\x4a\xdb\xcf\x56\x11\x12\x2b\x29\x12\x5e\x5d\x35\xd2\xd2\x22\x81\xaa\xb5\x33\xf0\x08\x32\xd5\x56\xb1\xf9\xea\xe5\x1d\x7d"); R1L = new uint256(R1Array); NegR1L = ~R1L; R1S = new uint160(R1Array.Take(20).ToArray()); NegR1S = ~R1S; NegR1Array = NegR1L.ToBytes(); R2Array = ToBytes("\x70\x32\x1d\x7c\x47\xa5\x6b\x40\x26\x7e\x0a\xc3\xa6\x9c\xb6\xbf\x13\x30\x47\xa3\x19\x2d\xda\x71\x49\x13\x72\xf0\xb4\xca\x81\xd7"); R2L = new uint256(R2Array); NegR2L = ~R2L; R2S = new uint160(R2Array.Take(20).ToArray()); NegR2S = ~R2S; NegR2Array = NegR2L.ToBytes(); ZeroArray = ToBytes("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"); ZeroL = new uint256(ZeroArray); ZeroS = new uint160(ZeroArray.Take(20).ToArray()); OneArray = ToBytes("\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"); OneL = new uint256(OneArray); OneS = new uint160(OneArray.Take(20).ToArray()); MaxArray = ToBytes("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"); MaxL = new uint256(MaxArray); MaxS = new uint160(MaxArray.Take(20).ToArray()); HalfL = OneL << 255; HalfS = OneS << 159; }
/// <summary> /// Gets the block. /// </summary> /// <param name="blockId">The block identifier.</param> /// <returns>Given a block hash (id) returns the requested block object.</returns> /// <exception cref="System.ArgumentNullException">blockId cannot be null.</exception> public async Task<Block> GetBlockAsync(uint256 blockId) { if (blockId == null) throw new ArgumentNullException("blockId"); var result = await SendRequestAsync("block", _format, blockId.ToString()).ConfigureAwait(false); ; return new Block(result); }
public ColoredTransaction GetFromCache(uint256 txId) { using(_lock.LockRead()) { return _ColoredTransactions.TryGet(txId); } }
public async Task PutAsync(uint256 txId, Transaction tx) { foreach(var repo in _Repositories) { await repo.PutAsync(txId, tx).ConfigureAwait(false); } }
public static string GetId(uint256 txId, uint256 blockId, int height) { return string.Format("{0}-{1}-{2}", (blockId == null ? (int.MaxValue - 1) : height), (blockId ?? uint256.Zero), txId); }
public async Task<Transaction> GetAsync(uint256 txId) { var tx = await _Configuration.CreateIndexerClient().GetTransactionAsync(false, txId).ConfigureAwait(false); if (tx == null) return null; return tx.Transaction; }
public ECDSASignature Sign(uint256 hash) { AssertPrivateKey(); var signer = new DeterministicECDSA(); signer.setPrivateKey(PrivateKey); var sig = ECDSASignature.FromDER(signer.signHash(hash.ToBytes())); return sig.MakeCanonical(); }
public async Task<Transaction> GetAsync(uint256 txId) { foreach(var repo in _Repositories) { var result = await repo.GetAsync(txId).ConfigureAwait(false); if(result != null) return result; } return null; }
public static void Put(this IColoredTransactionRepository repo, uint256 txId, ColoredTransaction tx) { try { repo.PutAsync(txId, tx).Wait(); } catch(AggregateException aex) { ExceptionDispatchInfo.Capture(aex.InnerException).Throw(); } }
public Task PutAsync(uint256 txId, ColoredTransaction tx) { using(_lock.LockWrite()) { if(!_ColoredTransactions.ContainsKey(txId)) _ColoredTransactions.AddOrReplace(txId, tx); else _ColoredTransactions[txId] = tx; return _Inner.PutAsync(txId, tx); } }
internal static BalanceLocator ParseCore(string[] splitted, bool queryFormat) { if (splitted.Length < 2) throw InvalidUnconfirmedBalance(); uint date = ParseUint(splitted[1]); uint256 transactionId = null; if (splitted.Length >= 3) transactionId = new uint256(Encoders.Hex.DecodeData(splitted[2]), false); return new UnconfirmedBalanceLocator(Utils.UnixTimeToDateTime(date), transactionId); }
public static ColoredTransaction Get(this IColoredTransactionRepository repo, uint256 txId) { try { return repo.GetAsync(txId).Result; } catch(AggregateException aex) { ExceptionDispatchInfo.Capture(aex.InnerException).Throw(); return null; } }
/// <summary> /// Gets the block. /// </summary> /// <param name="blockId">The block identifier.</param> /// <returns>Given a block hash (id) returns the requested block object.</returns> /// <exception cref="System.ArgumentNullException">blockId cannot be null.</exception> public Block GetBlock(uint256 blockId) { try { return GetBlockAsync(blockId).Result; } catch(AggregateException aex) { ExceptionDispatchInfo.Capture(aex.InnerException).Throw(); throw; } }
public Coins GetCoins(uint256 txId) { try { return Index.GetAsync<Coins>(txId.ToString()).Result; } catch(AggregateException aex) { ExceptionDispatchInfo.Capture(aex.InnerException).Throw(); return null; //Can't happen } }
public BlockHeader(uint version, uint256 prev_block_hash, uint256 merkle_root_hash, uint timestamp, Target bits, uint nonce) { if(prev_block_hash == null) throw new ArgumentNullException("prev_block_hash"); if(merkle_root_hash == null) throw new ArgumentNullException("merkle_root_hash"); if(bits == null) throw new ArgumentNullException("bits"); Version = version; PrevBlockHash = prev_block_hash; MerkleRootHash = merkle_root_hash; Timestamp = timestamp; Bits = bits; Nonce = nonce; }
public Entity(uint256 txId, Transaction tx, uint256 blockId) { if(txId == null) txId = tx.GetHash(); Timestamp = DateTimeOffset.UtcNow; TxId = txId; Transaction = tx; BlockId = blockId; if(blockId == null) Type = TransactionEntryType.Mempool; else Type = TransactionEntryType.ConfirmedTransaction; }
public void BigEndian() { var big = Packer.BigEndian; var arr = new byte[] { 0x01, 0x02, 0x03, 0x04, 0xff }; CollectionAssert.AreEqual(arr.Reverse(), big.GetBytes(arr)); // booleans CollectionAssert.AreEqual(Hex2Bytes("01"), big.GetBytes(true)); CollectionAssert.AreEqual(Hex2Bytes("00"), big.GetBytes(false)); Assert.AreEqual(false, big.ToBoolean(Hex2Bytes("00"), 0)); Assert.AreEqual(true, big.ToBoolean(Hex2Bytes("01"), 0)); // chars CollectionAssert.AreEqual(Hex2Bytes("0061").Reverse(), big.GetBytes('a')); Assert.AreEqual('a', big.ToChar(Hex2Bytes("0061").Reverse().ToArray(), 0)); // shorts CollectionAssert.AreEqual(Hex2Bytes("3039").Reverse(), big.GetBytes((ushort)12345)); CollectionAssert.AreEqual(Hex2Bytes("3039").Reverse(), big.GetBytes((short)12345)); CollectionAssert.AreEqual(Hex2Bytes("CFC7").Reverse(), big.GetBytes((short)-12345)); Assert.AreEqual(12345, big.ToUInt16(Hex2Bytes("3039").Reverse().ToArray(), 0)); Assert.AreEqual(12345, big.ToInt16(Hex2Bytes("3039").Reverse().ToArray(), 0)); Assert.AreEqual(-12345, big.ToInt16(Hex2Bytes("CFC7").Reverse().ToArray(), 0)); // ints CollectionAssert.AreEqual(Hex2Bytes("0034B59F").Reverse(), big.GetBytes((uint)3454367)); CollectionAssert.AreEqual(Hex2Bytes("0034B59F").Reverse(), big.GetBytes(3454367)); CollectionAssert.AreEqual(Hex2Bytes("FFCB4A61").Reverse(), big.GetBytes(-3454367)); Assert.AreEqual(3454367, big.ToUInt32(Hex2Bytes("0034B59F").Reverse().ToArray(), 0)); Assert.AreEqual(3454367, big.ToInt32(Hex2Bytes("0034B59F").Reverse().ToArray(), 0)); Assert.AreEqual(-3454367, big.ToInt32(Hex2Bytes("FFCB4A61").Reverse().ToArray(), 0)); // long CollectionAssert.AreEqual(Hex2Bytes("000000506DA33CD5").Reverse(), big.GetBytes((ulong)345436798165)); CollectionAssert.AreEqual(Hex2Bytes("000000506DA33CD5").Reverse(), big.GetBytes(345436798165)); CollectionAssert.AreEqual(Hex2Bytes("FFFFFFAF925CC32B").Reverse(), big.GetBytes(-345436798165)); Assert.AreEqual(345436798165, big.ToUInt64(Hex2Bytes("000000506DA33CD5").Reverse().ToArray(), 0)); Assert.AreEqual(345436798165, big.ToInt64(Hex2Bytes("000000506DA33CD5").Reverse().ToArray(), 0)); Assert.AreEqual(-345436798165, big.ToInt64(Hex2Bytes("FFFFFFAF925CC32B").Reverse().ToArray(), 0)); var u256 = new uint256(345436798165); var u256b = Hex2Bytes("000000000000000000000000000000000000000000000000000000506da33cd5"); CollectionAssert.AreEqual(u256b.Reverse(), big.GetBytes(u256)); Assert.AreEqual(u256, big.ToUInt256(u256b.Reverse().ToArray(), 0)); var u160 = new uint160(345436798165); var u160b = Hex2Bytes("000000000000000000000000000000506da33cd5"); CollectionAssert.AreEqual(u160b.Reverse(), big.GetBytes(u160)); Assert.AreEqual(u160, big.ToUInt160(u160b.Reverse().ToArray(), 0)); }
protected override void BuildTransaction(JObject json, Transaction tx) { var hash = new uint256((string)json.GetValue("hash")); tx.Version = (uint)json.GetValue("ver"); tx.LockTime = (uint)json.GetValue("lock_time"); var size = (uint)json.GetValue("size"); var vin = (JArray)json.GetValue("in"); int vinCount = (int)json.GetValue("vin_sz"); for(int i = 0 ; i < vinCount ; i++) { var jsonIn = (JObject)vin[i]; var txin = new NBitcoin.TxIn(); tx.Inputs.Add(txin); var prevout = (JObject)jsonIn.GetValue("prev_out"); txin.PrevOut.Hash = new uint256((string)prevout.GetValue("hash")); txin.PrevOut.N = (uint)prevout.GetValue("n"); var script = (string)jsonIn.GetValue("scriptSig"); if(script != null) { txin.ScriptSig = new Script(script); } else { var coinbase = (string)jsonIn.GetValue("coinbase"); txin.ScriptSig = new Script(Encoders.Hex.DecodeData(coinbase)); } var seq = jsonIn.GetValue("sequence"); if(seq != null) { txin.Sequence = (uint)seq; } } var vout = (JArray)json.GetValue("out"); int voutCount = (int)json.GetValue("vout_sz"); for(int i = 0 ; i < voutCount ; i++) { var jsonOut = (JObject)vout[i]; var txout = new NBitcoin.TxOut(); tx.Outputs.Add(txout); txout.Value = Money.Parse((string)jsonOut.GetValue("value")); txout.ScriptPubKey = new Script((string)jsonOut.GetValue("scriptPubKey")); } }
public Block GetBlock(uint256 id, List<byte[]> searchedData) { Block result = null; if(_Blocks.TryGetValue(id, out result)) return result; result = Inner.GetBlock(id, searchedData); _Blocks.AddOrUpdate(id, result, (i, b) => b); while(_Blocks.Count > MaxCachedBlock) { var removed = TakeRandom(_Blocks.Keys.ToList()); Block ignored = null; _Blocks.TryRemove(removed, out ignored); } return result; }
protected override void BuildTransaction(JObject json, Transaction tx) { var txid = new uint256((string)json.GetValue("txid")); tx.Version = (uint)json.GetValue("version"); tx.LockTime = (uint)json.GetValue("locktime"); var vin = (JArray)json.GetValue("vin"); for(int i = 0 ; i < vin.Count ; i++) { var jsonIn = (JObject)vin[i]; var txin = new NBitcoin.TxIn(); tx.Inputs.Add(txin); var script = (JObject)jsonIn.GetValue("scriptSig"); if(script != null) { txin.ScriptSig = new Script(Encoders.Hex.DecodeData((string)script.GetValue("hex"))); txin.PrevOut.Hash = new uint256((string)jsonIn.GetValue("txid")); txin.PrevOut.N = (uint)jsonIn.GetValue("vout"); } else { var coinbase = (string)jsonIn.GetValue("coinbase"); txin.ScriptSig = new Script(Encoders.Hex.DecodeData(coinbase)); } txin.Sequence = (uint)jsonIn.GetValue("sequence"); } var vout = (JArray)json.GetValue("vout"); for(int i = 0 ; i < vout.Count ; i++) { var jsonOut = (JObject)vout[i]; var txout = new NBitcoin.TxOut(); tx.Outputs.Add(txout); var btc = (decimal)jsonOut.GetValue("value"); var satoshis = btc * Money.COIN; txout.Value = new Money((long)(satoshis)); var script = (JObject)jsonOut.GetValue("scriptPubKey"); txout.ScriptPubKey = new Script(Encoders.Hex.DecodeData((string)script.GetValue("hex"))); } }
public void uitnSerializationTests() { MemoryStream ms = new MemoryStream(); BitcoinStream stream = new BitcoinStream(ms, true); var v = new uint256("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); var vless = new uint256("00000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); var vplus = new uint256("00000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); stream.ReadWrite(ref v); Assert.NotNull(v); ms.Position = 0; stream = new BitcoinStream(ms, false); uint256 v2 = uint256.Zero; stream.ReadWrite(ref v2); Assert.Equal(v, v2); v2 = null; ms.Position = 0; stream.ReadWrite(ref v2); Assert.Equal(v, v2); List<uint256> vs = new List<uint256>() { v,vless,vplus }; ms = new MemoryStream(); stream = new BitcoinStream(ms, true); stream.ReadWrite(ref vs); Assert.True(vs.Count == 3); ms.Position = 0; stream = new BitcoinStream(ms, false); List<uint256> vs2 = new List<uint256>(); stream.ReadWrite(ref vs2); Assert.True(vs2.SequenceEqual(vs)); ms.Position = 0; vs2 = null; stream.ReadWrite(ref vs2); Assert.True(vs2.SequenceEqual(vs)); }
public async Task<ColoredTransaction> GetAsync(uint256 txId) { ColoredTransaction result = null; bool found; using(_lock.LockRead()) { found = _ColoredTransactions.TryGetValue(txId, out result); } if(!found) { result = await _Inner.GetAsync(txId).ConfigureAwait(false); using(_lock.LockWrite()) { _ColoredTransactions.AddOrReplace(txId, result); } } return result; }
public void CanSerializeOrderedBalanceToEntity() { uint256 txId = new uint256(RandomUtils.GetBytes(32)); Script script = CreateScript(512); OrderedBalanceChange balance = new OrderedBalanceChange(txId, script, null, null, 0); Assert.Equal(script, balance.ScriptPubKey); var entity = balance.ToEntity(); Assert.False(entity.Properties.ContainsKey("h")); balance = new OrderedBalanceChange(entity); Assert.Equal(script, balance.ScriptPubKey); script = CreateScript(513); balance = new OrderedBalanceChange(txId, script, null, null, 0); Assert.Equal(script, balance.ScriptPubKey); entity = balance.ToEntity(); Assert.True(entity.Properties.ContainsKey("h")); balance = new OrderedBalanceChange(entity); Assert.Equal(script, balance.ScriptPubKey); }
public void uintTests() { var v = new uint256("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); var v2 = new uint256("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); var vless = new uint256("00000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); var vplus = new uint256("00000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); Assert.Equal("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", v.ToString()); Assert.Equal(new uint256("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), v); Assert.Equal(new uint256("0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), v); Assert.Equal(uint256.Parse("0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), v); Assert.True(v < vplus); Assert.True(v > vless); uint256 unused; Assert.True(uint256.TryParse("0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", out unused)); Assert.True(uint256.TryParse("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", out unused)); Assert.True(uint256.TryParse("00000000ffffFFfFffffffffffffffffffffffffffffffffffffffffffffffff", out unused)); Assert.False(uint256.TryParse("00000000gfffffffffffffffffffffffffffffffffffffffffffffffffffffff", out unused)); Assert.False(uint256.TryParse("100000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", out unused)); Assert.False(uint256.TryParse("1100000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", out unused)); Assert.Throws<FormatException>(() => uint256.Parse("1100000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); Assert.Throws<FormatException>(() => uint256.Parse("100000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); uint256.Parse("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); Assert.Throws<FormatException>(() => uint256.Parse("000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); Assert.True(v >= v2); Assert.True(v <= v2); Assert.False(v < v2); Assert.False(v > v2); Assert.True(v.ToBytes()[0] == 0xFF); Assert.True(v.ToBytes(false)[0] == 0x00); AssertEquals(v, new uint256(v.ToBytes())); AssertEquals(v, new uint256(v.ToBytes(false), false)); Assert.Equal(0xFF, v.GetByte(0)); Assert.Equal(0x00, v.GetByte(31)); Assert.Equal(0x39, new uint256("39000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffff").GetByte(31)); Assert.Throws<ArgumentOutOfRangeException>(() => v.GetByte(32)); }
public void CanParseTransaction() { var tests = TestCase.read_json("data/can_parse_transaction.json"); foreach(var test in tests.Select(t => t.GetDynamic(0))) { string raw = test.Raw; Transaction tx = new Transaction(raw); Assert.Equal((int)test.JSON.vin_sz, tx.Inputs.Count); Assert.Equal((int)test.JSON.vout_sz, tx.Outputs.Count); Assert.Equal((uint)test.JSON.lock_time, tx.LockTime); for(int i = 0 ; i < tx.Inputs.Count ; i++) { var actualVIn = tx.Inputs[i]; var expectedVIn = test.JSON.@in[i]; Assert.Equal(new uint256((string)expectedVIn.prev_out.hash), actualVIn.PrevOut.Hash); Assert.Equal((uint)expectedVIn.prev_out.n, actualVIn.PrevOut.N); if(expectedVIn.sequence != null) Assert.Equal((uint)expectedVIn.sequence, actualVIn.Sequence); Assert.Equal((string)expectedVIn.scriptSig, actualVIn.ScriptSig.ToString()); //Can parse the string Assert.Equal((string)expectedVIn.scriptSig, (string)expectedVIn.scriptSig.ToString()); } for(int i = 0 ; i < tx.Outputs.Count ; i++) { var actualVOut = tx.Outputs[i]; var expectedVOut = test.JSON.@out[i]; Assert.Equal((string)expectedVOut.scriptPubKey, actualVOut.ScriptPubKey.ToString()); Assert.Equal(Money.Parse((string)expectedVOut.value), actualVOut.Value); } var hash = (string)test.JSON.hash; var expectedHash = new uint256(Encoders.Hex.DecodeData(hash), false); Assert.Equal(expectedHash, tx.GetHash()); } }
/// <inheritdoc /> public async Task <Transaction> GetTransaction(uint256 trxid) { return((await this.InfoAsync(trxid))?.Trx); }
/// <summary> /// Get the a whole block /// </summary> /// <param name="blockId"></param> /// <returns></returns> public async Task <RPCBlock> GetRPCBlock(uint256 blockId) { var resp = await SendCommandAsync("getblock", blockId.ToString(), false).ConfigureAwait(false); return(SatoshiBlockFormatter.Parse(resp.Result as JObject)); }
public async Task <BlockHeader> GetBlockHeaderAsync(uint256 blockHash) { var resp = await SendCommandAsync("getblock", blockHash.ToString()).ConfigureAwait(false); return(ParseBlockHeader(resp)); }
/// <summary> /// Gets the unspent outputs for a given transaction id. /// </summary> /// <param name="txid">Transaction identifier.</param> /// <returns>The unspent outputs.</returns> public UnspentOutputs GetCoins(uint256 txid) { return(this.Set.AccessCoins(txid)); }
public BlindedOutputWithNonceIndex(int n, uint256 blindedOutput) { N = n; BlindedOutput = blindedOutput; }
public void SetBestBlock(uint256 blockId) { Index.PutAsync("B", blockId); }
public async Task FilterBuilderTestAsync() { using (var builder = await NodeBuilder.CreateAsync()) { await builder.CreateNodeAsync(); await builder.StartAllAsync(); CoreNode regtestNode = builder.Nodes[0]; regtestNode.Generate(101); RPCClient rpc = regtestNode.CreateRpcClient(); var indexBuilderServiceDir = Path.Combine(SharedFixture.DataDir, nameof(IndexBuilderService)); var indexFilePath = Path.Combine(indexBuilderServiceDir, $"Index{rpc.Network}.dat"); var utxoSetFilePath = Path.Combine(indexBuilderServiceDir, $"UtxoSet{rpc.Network}.dat"); var indexBuilderService = new IndexBuilderService(rpc, indexFilePath, utxoSetFilePath); try { indexBuilderService.Synchronize(); // Test initial synchronization. var times = 0; uint256 firstHash = await rpc.GetBlockHashAsync(0); while (indexBuilderService.GetFilterLinesExcluding(firstHash, 102, out _).filters.Count() != 101) { if (times > 500) // 30 sec { throw new TimeoutException($"{nameof(IndexBuilderService)} test timed out."); } await Task.Delay(100); times++; } // Test later synchronization. regtestNode.Generate(10); times = 0; while (indexBuilderService.GetFilterLinesExcluding(firstHash, 112, out bool found5).filters.Count() != 111) { Assert.True(found5); if (times > 500) // 30 sec { throw new TimeoutException($"{nameof(IndexBuilderService)} test timed out."); } await Task.Delay(100); times++; } // Test correct number of filters is received. var hundredthHash = await rpc.GetBlockHashAsync(100); Assert.Equal(11, indexBuilderService.GetFilterLinesExcluding(hundredthHash, 12, out bool found).filters.Count()); Assert.True(found); var bestHash = await rpc.GetBestBlockHashAsync(); Assert.Empty(indexBuilderService.GetFilterLinesExcluding(bestHash, 1, out bool found2).filters); Assert.True(found2); Assert.Empty(indexBuilderService.GetFilterLinesExcluding(uint256.Zero, 1, out bool found3).filters); Assert.False(found3); // Test filter block hashes are correct. var filters = indexBuilderService.GetFilterLinesExcluding(firstHash, 112, out bool found4).filters.ToArray(); Assert.True(found4); for (int i = 0; i < 111; i++) { var expectedHash = await rpc.GetBlockHashAsync(i + 1); var filterModel = FilterModel.FromLine(filters[i], i); Assert.Equal(expectedHash, filterModel.BlockHash); Assert.Null(filterModel.Filter); } } finally { if (!(indexBuilderService is null)) { await indexBuilderService.StopAsync(); } } } }
public async Task <SubmitTransactionsResponse> SubmitTransactionsAsync(IEnumerable <SubmitTransaction> requestEnum, UserAndIssuer user) { var request = requestEnum.ToArray(); logger.LogInformation($"Processing {request.Length} incoming transactions"); // Take snapshot of current metadata and use use it for all transactions var info = await blockChainInfo.GetInfoAsync(); var currentMinerId = await minerId.GetCurrentMinerIdAsync(); var consolidationParameters = info.ConsolidationTxParameters; // Use the same quotes for all transactions in single request var quotes = feeQuoteRepository.GetValidFeeQuotesByIdentity(user).ToArray(); if (quotes == null || !quotes.Any()) { throw new Exception("No fee quotes available"); } var responses = new List <SubmitTransactionOneResponse>(); var transactionsToSubmit = new List <(string transactionId, SubmitTransaction transaction, bool allowhighfees, bool dontCheckFees, bool listUnconfirmedAncestors, Dictionary <string, object> config)>(); int failureCount = 0; IDictionary <uint256, byte[]> allTxs = new Dictionary <uint256, byte[]>(); foreach (var oneTx in request) { if (!string.IsNullOrEmpty(oneTx.MerkleFormat) && !MerkleFormat.ValidFormats.Any(x => x == oneTx.MerkleFormat)) { AddFailureResponse(null, $"Invalid merkle format {oneTx.MerkleFormat}. Supported formats: {String.Join(",", MerkleFormat.ValidFormats)}.", ref responses); failureCount++; continue; } if ((oneTx.RawTx == null || oneTx.RawTx.Length == 0) && string.IsNullOrEmpty(oneTx.RawTxString)) { AddFailureResponse(null, $"{nameof(SubmitTransaction.RawTx)} is required", ref responses); failureCount++; continue; } if (oneTx.RawTx == null) { try { oneTx.RawTx = HelperTools.HexStringToByteArray(oneTx.RawTxString); } catch (Exception ex) { AddFailureResponse(null, ex.Message, ref responses); failureCount++; continue; } } uint256 txId = Hashes.DoubleSHA256(oneTx.RawTx); string txIdString = txId.ToString(); logger.LogInformation($"Processing transaction: { txIdString }"); if (oneTx.MerkleProof && (appSettings.DontParseBlocks.Value || appSettings.DontInsertTransactions.Value)) { AddFailureResponse(txIdString, $"Transaction requires merkle proof notification but this instance of mAPI does not support callbacks", ref responses); failureCount++; continue; } if (oneTx.DsCheck && (appSettings.DontParseBlocks.Value || appSettings.DontInsertTransactions.Value)) { AddFailureResponse(txIdString, $"Transaction requires double spend notification but this instance of mAPI does not support callbacks", ref responses); failureCount++; continue; } if (allTxs.ContainsKey(txId)) { AddFailureResponse(txIdString, "Transaction with this id occurs more than once within request", ref responses); failureCount++; continue; } var vc = new ValidationContext(oneTx); var errors = oneTx.Validate(vc); if (errors.Any()) { AddFailureResponse(txIdString, string.Join(",", errors.Select(x => x.ErrorMessage)), ref responses); failureCount++; continue; } allTxs.Add(txId, oneTx.RawTx); bool okToMine = false; bool okToRelay = false; Dictionary <string, object> policies = null; if (await txRepository.TransactionExistsAsync(txId.ToBytes())) { AddFailureResponse(txIdString, "Transaction already known", ref responses); failureCount++; continue; } Transaction transaction = null; CollidedWith[] colidedWith = Array.Empty <CollidedWith>(); Exception exception = null; string[] prevOutsErrors = Array.Empty <string>(); try { transaction = HelperTools.ParseBytesToTransaction(oneTx.RawTx); if (transaction.IsCoinBase) { throw new ExceptionWithSafeErrorMessage("Invalid transaction - coinbase transactions are not accepted"); } var(sumPrevOuputs, prevOuts) = await CollectPreviousOuputs(transaction, new ReadOnlyDictionary <uint256, byte[]>(allTxs), rpcMultiClient); prevOutsErrors = prevOuts.Where(x => !string.IsNullOrEmpty(x.Error)).Select(x => x.Error).ToArray(); colidedWith = prevOuts.Where(x => x.CollidedWith != null).Select(x => x.CollidedWith).ToArray(); logger.LogInformation($"CollectPreviousOuputs for {txIdString} returned { prevOuts.Length } prevOuts ({prevOutsErrors.Length } prevOutsErrors, {colidedWith.Length} colidedWith)."); if (appSettings.CheckFeeDisabled.Value || IsConsolidationTxn(transaction, consolidationParameters, prevOuts)) { logger.LogInformation($"{txIdString}: appSettings.CheckFeeDisabled { appSettings.CheckFeeDisabled }"); (okToMine, okToRelay) = (true, true); } else { logger.LogInformation($"Starting with CheckFees calculation for {txIdString} and { quotes.Length} quotes."); foreach (var feeQuote in quotes) { var(okToMineTmp, okToRelayTmp) = CheckFees(transaction, oneTx.RawTx.LongLength, sumPrevOuputs, feeQuote); if (GetCheckFeesValue(okToMineTmp, okToRelayTmp) > GetCheckFeesValue(okToMine, okToRelay)) { // save best combination (okToMine, okToRelay, policies) = (okToMineTmp, okToRelayTmp, feeQuote.PoliciesDict); } } logger.LogInformation($"Finished with CheckFees calculation for {txIdString} and { quotes.Length} quotes: { (okToMine, okToRelay, policies == null ? "" : string.Join(";", policies.Select(x => x.Key + "=" + x.Value)) )}."); } } catch (Exception ex) { exception = ex; } if (exception != null || colidedWith.Any() || transaction == null || prevOutsErrors.Any()) { var oneResponse = new SubmitTransactionOneResponse { Txid = txIdString, ReturnResult = ResultCodes.Failure, // Include non null ConflictedWith only if a collision has been detected ConflictedWith = !colidedWith.Any() ? null : colidedWith.Select( x => new SubmitTransactionConflictedTxResponse { Txid = x.TxId, Size = x.Size, Hex = x.Hex, }).ToArray() }; if (transaction is null) { oneResponse.ResultDescription = "Can not parse transaction"; } else if (exception is ExceptionWithSafeErrorMessage) { oneResponse.ResultDescription = exception.Message; } else if (exception != null) { oneResponse.ResultDescription = "Error fetching inputs"; } else if (oneResponse.ConflictedWith != null && oneResponse.ConflictedWith.Any(c => c.Txid == oneResponse.Txid)) { oneResponse.ResultDescription = "Transaction already in the mempool"; oneResponse.ConflictedWith = null; } else { // return "Missing inputs" regardless of error returned from gettxouts (which is usually "missing") oneResponse.ResultDescription = "Missing inputs"; } logger.LogError($"Can not calculate fee for {txIdString}. Error: {oneResponse.ResultDescription} Exception: {exception?.ToString() ?? ""}"); responses.Add(oneResponse); failureCount++; continue; } // Transactions was successfully analyzed if (!okToMine && !okToRelay) { AddFailureResponse(txIdString, "Not enough fees", ref responses); failureCount++; } else { bool allowHighFees = false; bool dontcheckfee = okToMine; bool listUnconfirmedAncestors = false; oneTx.TransactionInputs = transaction.Inputs.AsIndexedInputs().Select(x => new TxInput { N = x.Index, PrevN = x.PrevOut.N, PrevTxId = x.PrevOut.Hash.ToBytes() }).ToList(); if (oneTx.DsCheck) { foreach (TxInput txInput in oneTx.TransactionInputs) { var prevOut = await txRepository.GetPrevOutAsync(txInput.PrevTxId, txInput.PrevN); if (prevOut == null) { listUnconfirmedAncestors = true; break; } } } transactionsToSubmit.Add((txIdString, oneTx, allowHighFees, dontcheckfee, listUnconfirmedAncestors, policies)); } } logger.LogInformation($"TransactionsToSubmit: { transactionsToSubmit.Count }: { string.Join("; ", transactionsToSubmit.Select(x => x.transactionId))} "); RpcSendTransactions rpcResponse; Exception submitException = null; if (transactionsToSubmit.Any()) { // Submit all collected transactions in one call try { rpcResponse = await rpcMultiClient.SendRawTransactionsAsync( transactionsToSubmit.Select(x => (x.transaction.RawTx, x.allowhighfees, x.dontCheckFees, x.listUnconfirmedAncestors, x.config)) .ToArray()); } catch (Exception ex) { submitException = ex; rpcResponse = null; } } else { // Simulate empty response rpcResponse = new RpcSendTransactions(); } // Initialize common fields var result = new SubmitTransactionsResponse { Timestamp = clock.UtcNow(), MinerId = currentMinerId, CurrentHighestBlockHash = info.BestBlockHash, CurrentHighestBlockHeight = info.BestBlockHeight, // TxSecondMempoolExpiry // Remaining of the fields are initialized bellow }; if (submitException != null) { var unableToSubmit = transactionsToSubmit.Select(x => new SubmitTransactionOneResponse { Txid = x.transactionId, ReturnResult = ResultCodes.Failure, ResultDescription = "Error while submitting transactions to the node" // do not expose detailed error message. It might contain internal IPS etc }); logger.LogError($"Error while submitting transactions to the node {submitException}"); responses.AddRange(unableToSubmit); result.Txs = responses.ToArray(); result.FailureCount = result.Txs.Length; // all of the transactions have failed return(result); } else // submitted without error { var(submitFailureCount, transformed) = TransformRpcResponse(rpcResponse, transactionsToSubmit.Select(x => x.transactionId).ToArray()); responses.AddRange(transformed); result.Txs = responses.ToArray(); result.FailureCount = failureCount + submitFailureCount; if (!appSettings.DontInsertTransactions.Value) { var successfullTxs = transactionsToSubmit.Where(x => transformed.Any(y => y.ReturnResult == ResultCodes.Success && y.Txid == x.transactionId)); logger.LogInformation($"Starting with InsertTxsAsync: { successfullTxs.Count() }: { string.Join("; ", successfullTxs.Select(x => x.transactionId))} (TransactionsToSubmit: { transactionsToSubmit.Count })"); var watch = System.Diagnostics.Stopwatch.StartNew(); await txRepository.InsertTxsAsync(successfullTxs.Select(x => new Tx { CallbackToken = x.transaction.CallbackToken, CallbackUrl = x.transaction.CallbackUrl, CallbackEncryption = x.transaction.CallbackEncryption, DSCheck = x.transaction.DsCheck, MerkleProof = x.transaction.MerkleProof, MerkleFormat = x.transaction.MerkleFormat, TxExternalId = new uint256(x.transactionId), TxPayload = x.transaction.RawTx, ReceivedAt = clock.UtcNow(), TxIn = x.transaction.TransactionInputs }).ToList(), false); long unconfirmedAncestorsCount = 0; if (rpcResponse.Unconfirmed != null) { List <Tx> unconfirmedAncestors = new(); foreach (var unconfirmed in rpcResponse.Unconfirmed) { unconfirmedAncestors.AddRange(unconfirmed.Ancestors.Select(u => new Tx { TxExternalId = new uint256(u.Txid), ReceivedAt = clock.UtcNow(), TxIn = u.Vin.Select(i => new TxInput() { PrevTxId = (new uint256(i.Txid)).ToBytes(), PrevN = i.Vout }).ToList() }) ); } await txRepository.InsertTxsAsync(unconfirmedAncestors, true); unconfirmedAncestorsCount = unconfirmedAncestors.Count; } watch.Stop(); logger.LogInformation($"Finished with InsertTxsAsync: { successfullTxs.Count() } found unconfirmedAncestors { unconfirmedAncestorsCount } took {watch.ElapsedMilliseconds} ms."); } return(result); } }
public async Task <TransactionModel> GetRawTransactionAsync(string txid, [IntToBool] bool verbose = false, string blockHash = null) { Guard.NotEmpty(txid, nameof(txid)); if (!uint256.TryParse(txid, out uint256 trxid)) { throw new ArgumentException(nameof(trxid)); } uint256 hash = null; if (!string.IsNullOrEmpty(blockHash) && !uint256.TryParse(blockHash, out hash)) { throw new ArgumentException(nameof(blockHash)); } // Special exception for the genesis block coinbase transaction. if (trxid == this.Network.GetGenesis().GetMerkleRoot().Hash) { throw new RPCServerException(RPCErrorCode.RPC_INVALID_ADDRESS_OR_KEY, "The genesis block coinbase is not considered an ordinary transaction and cannot be retrieved."); } Transaction trx = null; ChainedHeaderBlock chainedHeaderBlock = null; if (hash == null) { // Look for the transaction in the mempool, and if not found, look in the indexed transactions. trx = (this.pooledTransaction == null ? null : await this.pooledTransaction.GetTransaction(trxid).ConfigureAwait(false)) ?? this.blockStore.GetTransactionById(trxid); if (trx == null) { throw new RPCServerException(RPCErrorCode.RPC_INVALID_ADDRESS_OR_KEY, "No such mempool transaction. Use -txindex to enable blockchain transaction queries."); } } else { // Retrieve the block specified by the block hash. chainedHeaderBlock = this.ConsensusManager.GetBlockData(hash); if (chainedHeaderBlock == null) { throw new RPCServerException(RPCErrorCode.RPC_INVALID_ADDRESS_OR_KEY, "Block hash not found."); } trx = chainedHeaderBlock.Block.Transactions.SingleOrDefault(t => t.GetHash() == trxid); if (trx == null) { throw new RPCServerException(RPCErrorCode.RPC_INVALID_ADDRESS_OR_KEY, "No such transaction found in the provided block."); } } if (verbose) { ChainedHeader block = chainedHeaderBlock != null ? chainedHeaderBlock.ChainedHeader : this.GetTransactionBlock(trxid); return(new TransactionVerboseModel(trx, this.Network, block, this.ChainState?.ConsensusTip)); } else { return(new TransactionBriefModel(trx)); } }
public Transaction GetTransaction(uint256 txid, bool include_watchonly = false, bool throwIfNotFound = true) { return(GetTransactionAsync(txid, include_watchonly, throwIfNotFound).GetAwaiter().GetResult()); }
/// <summary> /// Check whether a transaction exists in the mempool. /// </summary> public Task <bool> ExistsAsync(uint256 trxid) { return(this.MempoolLock.ReadAsync(() => this.memPool.Exists(trxid))); }
/// <inheritdoc /> public override Task SaveChangesAsync(IEnumerable <UnspentOutputs> unspentOutputs, IEnumerable <TxOut[]> originalOutputs, uint256 oldBlockHash, uint256 nextBlockHash) { throw new NotImplementedException(); }
/// <summary> /// Releases the block downloading task from the peer it has been assigned to /// and returns the block to the list of blocks the node wants to download. /// </summary> /// <param name="peerPendingDownloads">List of pending downloads tasks of the peer.</param> /// <param name="blockHash">Hash of the block which task should be released.</param> /// <returns><c>true</c> if the function succeeds, <c>false</c> if the block was not assigned to be downloaded by any peer.</returns> /// <remarks>The caller of this method is responsible for holding <see cref="lockObject"/>.</remarks> private bool ReleaseDownloadTaskAssignmentLocked(Dictionary <uint256, DownloadAssignment> peerPendingDownloads, uint256 blockHash) { this.logger.LogTrace("({0}.{1}:{2},{3}:'{4}')", nameof(peerPendingDownloads), nameof(peerPendingDownloads.Count), peerPendingDownloads.Count, nameof(blockHash), blockHash); bool res = false; if (this.assignedBlockTasks.Remove(blockHash) && peerPendingDownloads.Remove(blockHash)) { this.pendingInventoryVectors.Enqueue(blockHash); res = true; } this.logger.LogTrace("(-):{0}", res); return(res); }
/// <summary> /// When a peer downloads a block, it notifies the puller about the block by calling this method. /// <para> /// The downloaded task is removed from the list of pending downloads /// and it is also removed from the <see cref="assignedBlockTasks"/> - i.e. the task is no longer assigned to the peer. /// And finally, it is added to the list of downloaded blocks, provided that the block is not present there already. /// </para> /// </summary> /// <param name="peer">Peer that finished the download task.</param> /// <param name="blockHash">Hash of the downloaded block.</param> /// <param name="downloadedBlock">Description of the downloaded block.</param> /// <returns> /// <c>true</c> if the download task for the block was assigned to <paramref name="peer"/> /// and the task was removed and added to the list of downloaded blocks. /// <c>false</c> if the downloaded block has been assigned to another peer /// or if the block was already on the list of downloaded blocks. /// </returns> internal bool DownloadTaskFinished(BlockPullerBehavior peer, uint256 blockHash, DownloadedBlock downloadedBlock) { this.logger.LogTrace("({0}:'{1:x}',{2}:'{3}',{4}.{5}:{6})", nameof(peer), peer.GetHashCode(), nameof(blockHash), blockHash, nameof(downloadedBlock), nameof(downloadedBlock.Length), downloadedBlock.Length); bool error = false; bool res = false; double peerQualityAdjustment = 0; lock (this.lockObject) { BlockPullerBehavior peerAssigned; if (this.assignedBlockTasks.TryGetValue(blockHash, out peerAssigned)) { Dictionary <uint256, DownloadAssignment> peerPendingDownloads; if (this.peersPendingDownloads.TryGetValue(peer, out peerPendingDownloads)) { if (peer == peerAssigned) { DownloadAssignment downloadTask = null; peerPendingDownloads.TryGetValue(blockHash, out downloadTask); if (this.assignedBlockTasks.Remove(blockHash) && peerPendingDownloads.Remove(blockHash)) { // Task was assigned to this peer and was removed. if (this.downloadedBlocks.TryAdd(blockHash, downloadedBlock)) { long blockDownloadTime = downloadTask.Finish(); this.peerQuality.AddSample(peer, blockDownloadTime, downloadedBlock.Length); peerQualityAdjustment = this.peerQuality.CalculateQualityAdjustment(blockDownloadTime, downloadedBlock.Length); this.logger.LogTrace("Block '{0}' size '{1}' downloaded by peer '{2:x}' in {3} ms, peer's score will be adjusted by {4}.", blockHash, downloadedBlock.Length, peer.GetHashCode(), blockDownloadTime, peerQualityAdjustment); res = true; } else { this.logger.LogTrace("Block '{0}' already present on the list of downloaded blocks.", blockHash); } } else { // Task was assigned to this peer but the data are inconsistent. error = true; } } else { // Before this peer provided the block, it has been assigned to other peer, which is OK. this.logger.LogTrace("Incoming block '{0}' is assigned to peer '{1:x}', not to '{2:x}'.", blockHash, peerAssigned.GetHashCode(), peer.GetHashCode()); } } else { // Peer's pending downloads were probably released, which is OK. this.logger.LogTrace("Peer '{0:x}' has no assignments.", peer.GetHashCode()); } } else { // The task was probably assigned to other peer and that task completed before this peer provided the block, which is OK. this.logger.LogTrace("Incoming block '{0}' is not pending.", blockHash); } } if (error) { this.logger.LogCritical("Data structures inconsistency, please notify the devs."); // TODO: This exception is going to be silently discarded by Node_MessageReceived. throw new InvalidOperationException("Data structures inconsistency, please notify the devs."); } if (res) { peer.UpdateQualityScore(peerQualityAdjustment); } this.logger.LogTrace("(-):{0}", res); return(res); }
public void InternalTransfer_ToContractAddress() { // Ensure fixture is funded. this.mockChain.MineBlocks(1); // Deploy contract to send to ContractCompilationResult receiveCompilationResult = ContractCompiler.CompileFile("SmartContracts/BasicReceive.cs"); Assert.True(receiveCompilationResult.Success); BuildCreateContractTransactionResponse receiveResponse = this.node1.SendCreateContractTransaction(receiveCompilationResult.Compilation, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); Assert.NotNull(this.node1.GetCode(receiveResponse.NewContractAddress)); // Deploy contract to send from ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/BasicTransfer.cs"); Assert.True(compilationResult.Success); BuildCreateContractTransactionResponse preResponse = this.node1.SendCreateContractTransaction(compilationResult.Compilation, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); Assert.NotNull(this.node1.GetCode(preResponse.NewContractAddress)); decimal amount = 25; Money senderBalanceBefore = this.node1.WalletSpendableBalance; uint256 currentHash = this.node1.GetLastBlock().GetHash(); // Send amount to contract, which will send to contract address string[] parameters = new string[] { string.Format("{0}#{1}", (int)MethodParameterDataType.Address, receiveResponse.NewContractAddress) }; BuildCallContractTransactionResponse response = this.node1.SendCallContractTransaction( nameof(BasicTransfer.SendToAddress), preResponse.NewContractAddress, amount, parameters); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Contract doesn't maintain any balance Assert.Equal((ulong)0, this.node1.GetContractBalance(preResponse.NewContractAddress)); // Receiver contract now has balance Assert.Equal((ulong)new Money((int)amount, MoneyUnit.BTC), this.node1.GetContractBalance(receiveResponse.NewContractAddress)); // Receiver contract stored to state Assert.Equal(new byte[] { 1 }, this.node1.GetStorageValue(receiveResponse.NewContractAddress, BasicReceive.ReceiveKey)); // Log was stored - bloom filter should be non-zero Assert.NotEqual(new Bloom(), ((ISmartContractBlockHeader)lastBlock.Header).LogsBloom); // Block contains a condensing transaction Assert.Equal(3, lastBlock.Transactions.Count); Transaction condensingTransaction = lastBlock.Transactions[2]; Assert.Single(condensingTransaction.Outputs); // Entire balance was forwarded byte[] toBytes = condensingTransaction.Outputs[0].ScriptPubKey.ToBytes(); Assert.Equal((byte)ScOpcodeType.OP_INTERNALCONTRACTTRANSFER, toBytes[0]); uint160 toAddress = new uint160(toBytes.Skip(1).ToArray()); Assert.Equal(receiveResponse.NewContractAddress, toAddress.ToBase58Address(this.node1.CoreNode.FullNode.Network)); Assert.Equal(new Money((long)amount, MoneyUnit.BTC), condensingTransaction.Outputs[0].Value); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.Equal(lastBlock.GetHash().ToString(), receipt.BlockHash); Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash); Assert.Single(receipt.Logs); Assert.Equal(receiveResponse.NewContractAddress, receipt.Logs[0].Address); Assert.True(receipt.Success); Assert.True(receipt.GasUsed > GasPriceList.BaseCost); Assert.Null(receipt.NewContractAddress); Assert.Equal(this.node1.MinerAddress.Address, receipt.From); Assert.Null(receipt.Error); Assert.Equal(preResponse.NewContractAddress, receipt.To); }
public BlockHeader GetBlockHeader(uint256 blockHash) { var resp = SendCommand("getblock", blockHash.ToString()); return(ParseBlockHeader(resp)); }
private ulong Cheap(uint256 v) { return Utils.ToUInt64(v.ToBytes(), true); }
/// <summary> /// Get the a whole block /// </summary> /// <param name="blockId"></param> /// <returns></returns> public async Task <Block> GetBlockAsync(uint256 blockId) { var resp = await SendCommandAsync("getblock", blockId.ToString(), false).ConfigureAwait(false); return(new Block(Encoders.Hex.DecodeData(resp.Result.ToString()))); }
internal int GetNewBucket(uint256 nKey) { return GetNewBucket(nKey, Source); }
public void InternalTransfer_FromConstructor() { // Ensure fixture is funded. this.mockChain.MineBlocks(1); decimal amount = 25; Money senderBalanceBefore = this.node1.WalletSpendableBalance; uint256 currentHash = this.node1.GetLastBlock().GetHash(); // Deploy contract ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/TransferFromConstructor.cs"); Assert.True(compilationResult.Success); uint160 walletUint160 = new uint160(1); string address = walletUint160.ToBase58Address(this.node1.CoreNode.FullNode.Network); string[] parameters = new string[] { string.Format("{0}#{1}", (int)MethodParameterDataType.Address, address) }; BuildCreateContractTransactionResponse response = this.node1.SendCreateContractTransaction(compilationResult.Compilation, amount, parameters); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); Assert.NotNull(this.node1.GetCode(response.NewContractAddress)); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Block contains a condensing transaction Assert.Equal(3, lastBlock.Transactions.Count); Transaction condensingTransaction = lastBlock.Transactions[2]; Assert.Equal(2, condensingTransaction.Outputs.Count); // 1 output which is contract maintaining its balance byte[] toBytes = condensingTransaction.Outputs[0].ScriptPubKey.ToBytes(); Assert.Equal((byte)ScOpcodeType.OP_INTERNALCONTRACTTRANSFER, toBytes[0]); uint160 toAddress = new uint160(toBytes.Skip(1).ToArray()); Assert.Equal(response.NewContractAddress, toAddress.ToBase58Address(this.node1.CoreNode.FullNode.Network)); Assert.Equal(new Money((long)amount, MoneyUnit.BTC) / 2, condensingTransaction.Outputs[1].Value); // 1 output to address sent in params uint160 transferReceiver = this.senderRetriever.GetAddressFromScript(condensingTransaction.Outputs[1].ScriptPubKey).Sender; Assert.Equal(walletUint160, transferReceiver); Assert.Equal(new Money((long)amount, MoneyUnit.BTC) / 2, condensingTransaction.Outputs[1].Value); // Contract maintains half the balance Assert.Equal((ulong)new Money((long)amount, MoneyUnit.BTC) / 2, this.node1.GetContractBalance(response.NewContractAddress)); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.Equal(lastBlock.GetHash().ToString(), receipt.BlockHash); Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash); Assert.Empty(receipt.Logs); // TODO: Could add logs to this test Assert.True(receipt.Success); Assert.True(receipt.GasUsed > GasPriceList.BaseCost); Assert.Equal(response.NewContractAddress, receipt.NewContractAddress); Assert.Equal(this.node1.MinerAddress.Address, receipt.From); Assert.Null(receipt.Error); Assert.Null(receipt.To); }
/// <summary> /// Gets transaction info for a specific transaction in memory pool. /// </summary> /// <param name="hash">Hash of the transaction to query.</param> /// <returns>Transaction information.</returns> public Task <TxMempoolInfo> InfoAsync(uint256 hash) { return(this.MempoolLock.ReadAsync(() => this.Info(hash))); }
internal int GetTriedBucket(uint256 nKey) { UInt64 hash1 = Cheap(Hashes.Hash256(nKey.ToBytes().Concat(Address.GetKey()).ToArray())); UInt64 hash2 = Cheap(Hashes.Hash256(nKey.ToBytes().Concat(Address.Endpoint.Address.GetGroup()).Concat(Utils.ToBytes(hash1 % AddressManager.ADDRMAN_TRIED_BUCKETS_PER_GROUP, true)).ToArray())); return (int)(hash2 % ADDRMAN_TRIED_BUCKET_COUNT); }
public void InternalTransfer_BetweenContracts() { // Ensure fixture is funded. this.mockChain.MineBlocks(1); // Deploy contract to send to ContractCompilationResult receiveCompilationResult = ContractCompiler.CompileFile("SmartContracts/NestedCallsReceiver.cs"); Assert.True(receiveCompilationResult.Success); BuildCreateContractTransactionResponse receiveResponse = this.node1.SendCreateContractTransaction(receiveCompilationResult.Compilation, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); Assert.NotNull(this.node1.GetCode(receiveResponse.NewContractAddress)); // Deploy contract to send from ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/NestedCallsStarter.cs"); Assert.True(compilationResult.Success); BuildCreateContractTransactionResponse preResponse = this.node1.SendCreateContractTransaction(compilationResult.Compilation, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); Assert.NotNull(this.node1.GetCode(preResponse.NewContractAddress)); decimal amount = 25; Money senderBalanceBefore = this.node1.WalletSpendableBalance; uint256 currentHash = this.node1.GetLastBlock().GetHash(); string[] parameters = new string[] { string.Format("{0}#{1}", (int)MethodParameterDataType.Address, receiveResponse.NewContractAddress) }; BuildCallContractTransactionResponse response = this.node1.SendCallContractTransaction(nameof(NestedCallsStarter.Start), preResponse.NewContractAddress, amount, parameters); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Storage set correctly Assert.Equal(BitConverter.GetBytes(NestedCallsStarter.Return), this.node1.GetStorageValue(preResponse.NewContractAddress, NestedCallsStarter.Key)); // Block contains a condensing transaction Assert.Equal(3, lastBlock.Transactions.Count); Transaction condensingTransaction = lastBlock.Transactions[2]; Assert.Equal(2, condensingTransaction.Outputs.Count); // 1 output which is starting contract byte[] toBytes = condensingTransaction.Outputs[0].ScriptPubKey.ToBytes(); Assert.Equal((byte)ScOpcodeType.OP_INTERNALCONTRACTTRANSFER, toBytes[0]); uint160 toAddress = new uint160(toBytes.Skip(1).ToArray()); Assert.Equal(preResponse.NewContractAddress, toAddress.ToBase58Address(this.node1.CoreNode.FullNode.Network)); // Received 1/2 the sent funds + 1/2 of those funds Money transferAmount1 = new Money((long)amount, MoneyUnit.BTC) / 2; Money transferAmount2 = new Money((long)amount, MoneyUnit.BTC) / 4; Assert.Equal(transferAmount1 + transferAmount2, condensingTransaction.Outputs[0].Value); Assert.Equal((ulong)(transferAmount1 + transferAmount2), this.node1.GetContractBalance(preResponse.NewContractAddress)); // 1 output to other deployed contract toBytes = condensingTransaction.Outputs[1].ScriptPubKey.ToBytes(); Assert.Equal((byte)ScOpcodeType.OP_INTERNALCONTRACTTRANSFER, toBytes[0]); toAddress = new uint160(toBytes.Skip(1).ToArray()); Assert.Equal(receiveResponse.NewContractAddress, toAddress.ToBase58Address(this.node1.CoreNode.FullNode.Network)); // Received 1/2 the sent funds, but sent 1/2 of those funds back Assert.Equal(new Money((long)amount, MoneyUnit.BTC) - (transferAmount1 + transferAmount2), condensingTransaction.Outputs[1].Value); Assert.Equal((ulong)(new Money((long)amount, MoneyUnit.BTC) - (transferAmount1 + transferAmount2)), this.node1.GetContractBalance(receiveResponse.NewContractAddress)); }
public void SetBestBlock(uint256 blockId) { Index.PutAsync("B", blockId.AsBitcoinSerializable()); }
public void InternalTransfer_ToWalletAddress() { // Ensure fixture is funded. this.mockChain.MineBlocks(1); // Deploy contract ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/BasicTransfer.cs"); Assert.True(compilationResult.Success); BuildCreateContractTransactionResponse preResponse = this.node1.SendCreateContractTransaction(compilationResult.Compilation, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); Assert.NotNull(this.node1.GetCode(preResponse.NewContractAddress)); decimal amount = 25; Money senderBalanceBefore = this.node1.WalletSpendableBalance; uint256 currentHash = this.node1.GetLastBlock().GetHash(); // Send amount to contract, which will send to wallet address (address without code) uint160 walletUint160 = new uint160(1); string address = walletUint160.ToBase58Address(this.node1.CoreNode.FullNode.Network); string[] parameters = new string[] { string.Format("{0}#{1}", (int)MethodParameterDataType.Address, address) }; BuildCallContractTransactionResponse response = this.node1.SendCallContractTransaction( nameof(BasicTransfer.SendToAddress), preResponse.NewContractAddress, amount, parameters); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Block contains a condensing transaction Assert.Equal(3, lastBlock.Transactions.Count); Transaction condensingTransaction = lastBlock.Transactions[2]; Assert.Single(condensingTransaction.Outputs); // Entire balance was forwarded, uint160 transferReceiver = this.senderRetriever.GetAddressFromScript(condensingTransaction.Outputs[0].ScriptPubKey).Sender; Assert.Equal(walletUint160, transferReceiver); Assert.Equal(new Money((long)amount, MoneyUnit.BTC), condensingTransaction.Outputs[0].Value); // Contract doesn't maintain any balance Assert.Equal((ulong)0, this.node1.GetContractBalance(preResponse.NewContractAddress)); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.Equal(lastBlock.GetHash().ToString(), receipt.BlockHash); Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash); Assert.Empty(receipt.Logs); // TODO: Could add logs to this test Assert.True(receipt.Success); Assert.True(receipt.GasUsed > GasPriceList.BaseCost); Assert.Null(receipt.NewContractAddress); Assert.Equal(this.node1.MinerAddress.Address, receipt.From); Assert.Null(receipt.Error); Assert.Equal(preResponse.NewContractAddress, receipt.To); }
public void InternalTransfer_Create_WithValueTransfer() { // Ensure fixture is funded. this.mockChain.MineBlocks(1); // Deploy contract ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/CreationTransfer.cs"); Assert.True(compilationResult.Success); BuildCreateContractTransactionResponse preResponse = this.node1.SendCreateContractTransaction(compilationResult.Compilation, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); Assert.NotNull(this.node1.GetCode(preResponse.NewContractAddress)); decimal amount = 25; Money senderBalanceBefore = this.node1.WalletSpendableBalance; uint256 currentHash = this.node1.GetLastBlock().GetHash(); // Send amount to contract, which will send to new address of contract it creates BuildCallContractTransactionResponse response = this.node1.SendCallContractTransaction( nameof(CreationTransfer.CreateAnotherContract), preResponse.NewContractAddress, amount); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Get created contract address - TODO FIX uint160 createdAddress = this.addressGenerator.GenerateAddress(response.TransactionId, 0); // Block contains a condensing transaction Assert.Equal(3, lastBlock.Transactions.Count); Transaction condensingTransaction = lastBlock.Transactions[2]; Assert.Single(condensingTransaction.Outputs); // Entire balance was forwarded, byte[] toBytes = condensingTransaction.Outputs[0].ScriptPubKey.ToBytes(); Assert.Equal((byte)ScOpcodeType.OP_INTERNALCONTRACTTRANSFER, toBytes[0]); uint160 toAddress = new uint160(toBytes.Skip(1).ToArray()); Assert.Equal(createdAddress, toAddress); Assert.Equal(new Money((long)amount, MoneyUnit.BTC), condensingTransaction.Outputs[0].Value); // Contract doesn't maintain any balance Assert.Equal((ulong)0, this.node1.GetContractBalance(preResponse.NewContractAddress)); // Created contract received full amount Assert.Equal((ulong)new Money((ulong)amount, MoneyUnit.BTC), this.node1.GetContractBalance(createdAddress.ToBase58Address(this.node1.CoreNode.FullNode.Network))); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.Equal(lastBlock.GetHash().ToString(), receipt.BlockHash); Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash); Assert.Empty(receipt.Logs); // TODO: Could add logs to this test Assert.True(receipt.Success); Assert.True(receipt.GasUsed > GasPriceList.BaseCost); Assert.Null(receipt.NewContractAddress); Assert.Equal(this.node1.MinerAddress.Address, receipt.From); Assert.Null(receipt.Error); Assert.Equal(preResponse.NewContractAddress, receipt.To); }
public InMemoryCoinView(uint256 blockHash) { this.blockHash = blockHash; }
/// <inheritdoc/> public bool IsMarkedInvalid(uint256 hashBlock) { return(this.invalidBlockHashStore.IsInvalid(hashBlock)); }
/// <summary> /// Validation of the witness commitment if its found. /// </summary> public Task ValidateWitnessCommitment(RuleContext context, Network network) { if (context.SkipValidation) { return(Task.CompletedTask); } DeploymentFlags deploymentFlags = context.Flags; Block block = context.ValidationContext.BlockToValidate; // Validation for witness commitments. // * We compute the witness hash (which is the hash including witnesses) of all the block's transactions, except the // coinbase (where 0x0000....0000 is used instead). // * The coinbase scriptWitness is a stack of a single 32-byte vector, containing a witness nonce (unconstrained). // * We build a merkle tree with all those witness hashes as leaves (similar to the hashMerkleRoot in the block header). // * There must be at least one output whose scriptPubKey is a single 36-byte push, the first 4 bytes of which are // {0xaa, 0x21, 0xa9, 0xed}, and the following 32 bytes are SHA256^2(witness root, witness nonce). In case there are // multiple, the last one is used. bool fHaveWitness = false; if (deploymentFlags.ScriptFlags.HasFlag(ScriptVerify.Witness)) { Script commitment = GetWitnessCommitment(network, block); if (commitment != null) { uint256 hashWitness = BlockWitnessMerkleRoot(block, out bool _); // The malleation check is ignored; as the transaction tree itself // already does not permit it, it is impossible to trigger in the // witness tree. WitScript witness = block.Transactions[0].Inputs[0].WitScript; if ((witness.PushCount != 1) || (witness.Pushes.First().Length != 32)) { // Witness information is missing, activating witness requirement for peers is required. context.ValidationContext.MissingServices = NetworkPeerServices.NODE_WITNESS; this.Logger.LogTrace("(-)[BAD_WITNESS_NONCE_SIZE]"); ConsensusErrors.BadWitnessNonceSize.Throw(); } var hashed = new byte[64]; Buffer.BlockCopy(hashWitness.ToBytes(), 0, hashed, 0, 32); Buffer.BlockCopy(witness.Pushes.First(), 0, hashed, 32, 32); hashWitness = Hashes.Hash256(hashed); if (!this.EqualsArray(hashWitness.ToBytes(), commitment.ToBytes(true).Skip(6).ToArray(), 32)) { this.Logger.LogTrace("(-)[WITNESS_MERKLE_MISMATCH]"); ConsensusErrors.BadWitnessMerkleMatch.Throw(); } fHaveWitness = true; } } if (!fHaveWitness) { for (int i = 0; i < block.Transactions.Count; i++) { if (block.Transactions[i].HasWitness) { this.Logger.LogTrace("(-)[UNEXPECTED_WITNESS]"); ConsensusErrors.UnexpectedWitness.Throw(); } } } return(Task.CompletedTask); }
public bool HaveCoins(uint256 txId) { return GetCoins(txId) != null; }
/// <inheritdoc/> public void MarkBlockInvalid(uint256 hashBlock, DateTime?rejectedUntil = null) { this.invalidBlockHashStore.MarkInvalid(hashBlock, rejectedUntil); }
internal static bool VerifyChecksum(uint256 checksum, byte[] payload, int length) { return checksum == Hashes.Hash256(payload, 0, length).GetLow32(); }
/// <summary> /// Method called when a new block is downloaded and pushed to the puller. /// <para> /// This method is to be overridden by derived classes. In the base class it only logs the event. /// </para> /// </summary> /// <param name="blockHash">Hash of the newly downloaded block.</param> /// <param name="downloadedBlock">Desciption of the newly downloaded block.</param> /// <param name="cancellationToken">Cancellation token to be used by derived classes that allows the caller to cancel the execution of the operation.</param> public virtual void BlockPushed(uint256 blockHash, DownloadedBlock downloadedBlock, CancellationToken cancellationToken) { this.logger.LogTrace("({0}:'{1}',{2}.{3}:{4})", nameof(blockHash), blockHash, nameof(downloadedBlock), nameof(downloadedBlock.Length), downloadedBlock.Length); this.logger.LogTrace("(-)"); }