void ResolveRequest(string id, RPCException ex, Message rpy) { RequestInfo ri; lock (state_lock) { if (pending.TryGetValue(id, out ri)) { pending.Remove(id); } if (ri != null && ri.timeout != null) { ri.timeout.Dispose(); ri.timeout = null; } } if (ri == null) { if (rpy != null) { rpy.Discard(); } return; } if (ex != null) { Message.StreamToCallback(ri.cb, ex.AsHeader()); } else { ri.cb(rpy); } }
public async Task GetTransactionExistsInBlockButDoesntExistInWalletAsync() { // Transaction included in block at height 3. string txId = "5369de2c6b7b62902d303995e90406d82de48f8c5ed0e847618dcf4e5cde84a1"; using (NodeBuilder builder = NodeBuilder.Create(this)) { // Arrange. CoreNode node = builder.CreateStratisPosNode(this.network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest150Listener).Start(); //// Check transaction exists in block #3. BlockModel block = await $"http://localhost:{node.ApiPort}/api" .AppendPathSegment("blockstore/block") .SetQueryParams(new { hash = "57546d732a7cdf38135377fd3eddebbb928ec760c1e6a4b1b36e775b4ac2a3c7", outputJson = true }) .GetJsonAsync <BlockModel>(); block.Transactions.Should().ContainSingle(t => (string)t == txId); RPCClient rpc = node.CreateRPCClient(); Func <Task> getTransaction = async() => { await rpc.SendCommandAsync(RPCOperations.gettransaction, txId); }; RPCException exception = getTransaction.Should().Throw <RPCException>().Which; exception.RPCCode.Should().Be(RPCErrorCode.RPC_INVALID_ADDRESS_OR_KEY); exception.Message.Should().Be("Invalid or non-wallet transaction id."); } }
protected virtual void OnMessage(Message req, Action <Message> rpy) { req.Consume(1000000, (header, data, dlen, error) => { RPCRequestInfo ri = new RPCRequestInfo { RequestHeader = header, RequestData = data, RequestDataLength = dlen, RequestError = error, ResponseHeader = new JObject(), ResponseData = new byte[0], }; wq.Enqueue(() => { try { Execute(ri); } catch (Exception ex) { Logger.LogError("{0} Exception: {1}", ri.ActionInfo == null ? "(action not yet determined)" : ri.ActionInfo.Name.ToString(), ex); var rpcex = RPCException.Wrap(ex); ri.ResponseHeader ["error_code"] = rpcex.ErrorCode; ri.ResponseHeader ["error"] = rpcex.ErrorMessage; ri.ResponseHeader ["error_data"] = rpcex.ErrorData; } Message.StreamToCallback(rpy, ri.ResponseHeader, ri.ResponseData); }); }); }
public async Task GetTransactionExistsInBlockButDoesntExistInWalletAsync() { // Transaction included in block at height 3. string txId = "21f3b1fd361f50992db217ea16728acc6b3dbf49c8531e60f8a28d7f3bdf4674"; using (NodeBuilder builder = NodeBuilder.Create(this)) { // Arrange. CoreNode node = builder.CreateStratisPosNode(this.network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest150Listener).Start(); //// Check transaction exists in block #3. BlockModel block = await $"http://localhost:{node.ApiPort}/api" .AppendPathSegment("blockstore/block") .SetQueryParams(new { hash = "b1209de1c0347be83bb02a3bf9b70e33b06c82b91e68bc6392e6fb813cd5e4bd", outputJson = true }) .GetJsonAsync <BlockModel>(); block.Transactions.Should().ContainSingle(t => (string)t == txId); RPCClient rpc = node.CreateRPCClient(); Func <Task> getTransaction = async() => { await rpc.SendCommandAsync(RPCOperations.gettransaction, txId); }; RPCException exception = getTransaction.Should().Throw <RPCException>().Which; exception.RPCCode.Should().Be(RPCErrorCode.RPC_INVALID_ADDRESS_OR_KEY); exception.Message.Should().Be("Invalid or non-wallet transaction id."); } }
public async Task GetRawTransactionWithTransactionAndBlockHashInBlockchainAndNotIndexedAsync() { using (NodeBuilder builder = NodeBuilder.Create(this)) { var configParameters = new NodeConfigParameters { { "txindex", "0" } }; CoreNode node = builder.CreateStratisCustomPowNode(new BitcoinRegTest(), configParameters).WithWallet().Start(); TestHelper.MineBlocks(node, 5); // Get the last block we have. string lastBlockHash = await $"http://localhost:{node.ApiPort}/api" .AppendPathSegment("consensus/getbestblockhash") .GetJsonAsync <string>(); BlockTransactionDetailsModel tip = await $"http://localhost:{node.ApiPort}/api" .AppendPathSegment("blockstore/block") .SetQueryParams(new { hash = lastBlockHash, outputJson = true, showtransactiondetails = true }) .GetJsonAsync <BlockTransactionDetailsModel>(); string txId = tip.Transactions.First().TxId; RPCClient rpc = node.CreateRPCClient(); Func <Task> getTransaction = async() => { await rpc.SendCommandAsync(RPCOperations.getrawtransaction, txId); }; RPCException exception = getTransaction.Should().Throw <RPCException>().Which; exception.RPCCode.Should().Be(RPCErrorCode.RPC_INVALID_ADDRESS_OR_KEY); exception.Message.Should().Be("No such mempool transaction. Use -txindex to enable blockchain transaction queries."); } }
public async Task GetTransactionExistsInBlockButDoesntExistInWalletAsync() { using (NodeBuilder builder = NodeBuilder.Create(this)) { // Arrange. CoreNode node = builder.CreateStratisPosNode(this.network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest150Listener).Start(); ChainedHeader header = node.FullNode.ChainIndexer.GetHeader(3); Block fetchBlock = node.FullNode.NodeService <IBlockStore>().GetBlock(header.HashBlock); string blockHash = header.HashBlock.ToString(); // Transaction included in block at height 3. string txId = fetchBlock.Transactions[0].GetHash().ToString(); //// Check transaction exists in block #3. BlockModel block = await $"http://localhost:{node.ApiPort}/api" .AppendPathSegment("blockstore/block") .SetQueryParams(new { hash = blockHash, outputJson = true }) .GetJsonAsync <BlockModel>(); block.Transactions.Should().ContainSingle(t => (string)t == txId); RPCClient rpc = node.CreateRPCClient(); Func <Task> getTransaction = async() => { await rpc.SendCommandAsync(RPCOperations.gettransaction, txId); }; RPCException exception = getTransaction.Should().Throw <RPCException>().Which; exception.RPCCode.Should().Be(RPCErrorCode.RPC_INVALID_ADDRESS_OR_KEY); exception.Message.Should().Be("Invalid or non-wallet transaction id."); } }
private static bool IsTransient(RPCException ex) { return (ex.RPCCode == RPCErrorCode.RPC_IN_WARMUP || ex.Message.Contains("Loading wallet...") || ex.Message.Contains("Loading block index...") || ex.Message.Contains("Loading P2P addresses...") || ex.Message.Contains("Rewinding blocks...") || ex.Message.Contains("Verifying blocks...") || ex.Message.Contains("Loading addresses...")); }
public async Task <BroadcastResult> Broadcast( [ModelBinder(BinderType = typeof(DestinationModelBinder))] DerivationStrategyBase extPubKey) { var tx = new Transaction(); var stream = new BitcoinStream(Request.Body, false); tx.ReadWrite(stream); RPCException rpcEx = null; try { await RPC.SendRawTransactionAsync(tx); return(new BroadcastResult(true)); } catch (RPCException ex) { rpcEx = ex; Logs.Explorer.LogInformation($"Transaction {tx.GetHash()} failed to broadcast (Code: {ex.RPCCode}, Message: {ex.RPCCodeMessage}, Details: {ex.Message} )"); if (extPubKey != null && ex.Message.StartsWith("Missing inputs", StringComparison.OrdinalIgnoreCase)) { Logs.Explorer.LogInformation("Trying to broadcast unconfirmed of the wallet"); var transactions = GetAnnotatedTransactions(extPubKey).Where(t => t.Height == MempoolHeight).ToList(); transactions = transactions.TopologicalSort(DependsOn(transactions)).ToList(); foreach (var existing in transactions) { try { await RPC.SendRawTransactionAsync(existing.Record.Transaction); } catch { } } try { await RPC.SendRawTransactionAsync(tx); Logs.Explorer.LogInformation($"Broadcast success"); return(new BroadcastResult(true)); } catch (RPCException) { Logs.Explorer.LogInformation($"Transaction {tx.GetHash()} failed to broadcast (Code: {ex.RPCCode}, Message: {ex.RPCCodeMessage}, Details: {ex.Message} )"); } } return(new BroadcastResult(false) { RPCCode = rpcEx.RPCCode, RPCCodeMessage = rpcEx.RPCCodeMessage, RPCMessage = rpcEx.Message }); } }
public void GetRawTransactionWhenBlockNotFound() { using (NodeBuilder builder = NodeBuilder.Create(this)) { // Arrange. CoreNode node = builder.CreateStratisPosNode(this.network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest150Miner).Start(); // Act. RPCClient rpc = node.CreateRPCClient(); Func <Task> getTransaction = async() => { await rpc.SendCommandAsync(RPCOperations.getrawtransaction, uint256.Zero.ToString(), false, uint256.Zero.ToString()); }; // Assert. RPCException exception = getTransaction.Should().Throw <RPCException>().Which; exception.RPCCode.Should().Be(RPCErrorCode.RPC_INVALID_ADDRESS_OR_KEY); exception.Message.Should().Be("Block hash not found."); } }
public void GetRawTransactionDoesntExistInMempool() { string txId = "7922666d8f88e3af37cfc88ff410da82f02de913a75891258a808c387ebdee54"; using (NodeBuilder builder = NodeBuilder.Create(this)) { // Arrange. CoreNode node = builder.CreateStratisPosNode(this.network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest150Miner).Start(); RPCClient rpc = node.CreateRPCClient(); Func <Task> getTransaction = async() => { await rpc.SendCommandAsync(RPCOperations.getrawtransaction, txId); }; RPCException exception = getTransaction.Should().Throw <RPCException>().Which; exception.RPCCode.Should().Be(RPCErrorCode.RPC_INVALID_ADDRESS_OR_KEY); exception.Message.Should().Be("No such mempool transaction. Use -txindex to enable blockchain transaction queries."); } }
public void GetTransactionDoesntExistInWalletOrBlock() { string txId = "f13effbbfc1b3d556dbfa25129e09209c9c57ed2737457f5080b78984a8c8554"; using (NodeBuilder builder = NodeBuilder.Create(this)) { // Arrange. CoreNode node = builder.CreateStratisPosNode(this.network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest150Miner).Start(); RPCClient rpc = node.CreateRPCClient(); Func <Task> getTransaction = async() => { await rpc.SendCommandAsync(RPCOperations.gettransaction, txId); }; RPCException exception = getTransaction.Should().Throw <RPCException>().Which; exception.RPCCode.Should().Be(RPCErrorCode.RPC_INVALID_ADDRESS_OR_KEY); exception.Message.Should().Be("Invalid or non-wallet transaction id."); } }
public async Task GetRawTransactionDoesntExistInBlockAsync() { using (NodeBuilder builder = NodeBuilder.Create(this)) { // Arrange. CoreNode node = builder.CreateStratisPosNode(this.network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest150Miner).Start(); // Get the last block we have. string lastBlockHash = await $"http://localhost:{node.ApiPort}/api" .AppendPathSegment("consensus/getbestblockhash") .GetJsonAsync <string>(); RPCClient rpc = node.CreateRPCClient(); Func <Task> getTransaction = async() => { await rpc.SendCommandAsync(RPCOperations.getrawtransaction, uint256.Zero.ToString(), false, lastBlockHash); }; RPCException exception = getTransaction.Should().Throw <RPCException>().Which; exception.RPCCode.Should().Be(RPCErrorCode.RPC_INVALID_ADDRESS_OR_KEY); exception.Message.Should().Be("No such transaction found in the provided block."); } }
public async Task GetRawTransactionWithGenesisTransactionAsync() { using (NodeBuilder builder = NodeBuilder.Create(this)) { // Arrange. CoreNode node = builder.CreateStratisPosNode(this.network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest150Miner).Start(); // Get the genesis block. BlockModel block = await $"http://localhost:{node.ApiPort}/api" .AppendPathSegment("blockstore/block") .SetQueryParams(new { hash = "0x93925104d664314f581bc7ecb7b4bad07bcfabd1cfce4256dbd2faddcf53bd1f", outputJson = true }) .GetJsonAsync <BlockModel>(); RPCClient rpc = node.CreateRPCClient(); Func <Task> getTransaction = async() => { await rpc.SendCommandAsync(RPCOperations.getrawtransaction, block.MerkleRoot, false, block.Hash); }; RPCException exception = getTransaction.Should().Throw <RPCException>().Which; exception.RPCCode.Should().Be(RPCErrorCode.RPC_INVALID_ADDRESS_OR_KEY); exception.Message.Should().Be("The genesis block coinbase is not considered an ordinary transaction and cannot be retrieved."); } }
public static JObject SyncJsonRequest(string act, JObject header, JObject payload) { Logger.LogInfo("REQ {0} {1} {2}", act, JSON.Stringify(header), JSON.Stringify(payload)); using (var e = new ManualResetEvent(false)) { JObject result = null; RPCException exn = null; MakeJsonRequest(ActionName.Parse(act), header, payload, (ex, res) => { exn = ex; result = res; e.Set(); }); e.WaitOne(); Logger.LogInfo("RES {0} {1}", exn, JSON.Stringify(result)); if (exn != null) { throw exn; } return(result); } }
// the JS requestor uses a "forwardRequest" concept which is almost certainly a premature optimization and not duplicated here static public void MakeRequest(RequestLocalOptions opts, ActionName act, string envelope, Message req, Action <Message> on_rpy) { ServiceInfo si; ActionInfo ai; if (!discovery.FindService(act, envelope, opts.TargetIdent, out si, out ai)) { req.Discard(); Message.StreamToCallback(on_rpy, new RPCException("transport", "Action {0} not found", act).AsHeader()); return; } // important: aliases are processed here req.Header ["action"] = ai.Name.Namespace + '.' + ai.Name.Name; req.Header ["version"] = (double)ai.Name.Version; SOAClient client; try { client = GetConnection(si); } catch (Exception ex) { RPCException rpcex = RPCException.Wrap(ex); req.Discard(); Message.StreamToCallback(on_rpy, new RPCException("transport", "Cannot establish connection", rpcex, RPCException.DispatchFailure()).AsHeader()); return; } if (opts.Timeout == 0) { opts.Timeout = ai.Timeout; } client.Request(opts, req, on_rpy); }
public static bool IsInsufficientToken(this RPCException ex) { return(ex.RPCResult.Error?.Code == RPCErrorCode.RPC_TYPE_ERROR && ex.RPCResult.Error?.Message == "Sender has insufficient balance"); }
public async Task <BroadcastResult> Broadcast( string cryptoCode, [ModelBinder(BinderType = typeof(DestinationModelBinder))] DerivationStrategyBase extPubKey) { var network = GetNetwork(cryptoCode); var tx = network.NBitcoinNetwork.Consensus.ConsensusFactory.CreateTransaction(); var stream = new BitcoinStream(Request.Body, false); tx.ReadWrite(stream); var waiter = this.Waiters.GetWaiter(network); if (!waiter.RPCAvailable) { throw RPCUnavailable(); } var repo = RepositoryProvider.GetRepository(network); var chain = ChainProvider.GetChain(network); RPCException rpcEx = null; try { await waiter.RPC.SendRawTransactionAsync(tx); return(new BroadcastResult(true)); } catch (RPCException ex) { rpcEx = ex; Logs.Explorer.LogInformation($"{network.CryptoCode}: Transaction {tx.GetHash()} failed to broadcast (Code: {ex.RPCCode}, Message: {ex.RPCCodeMessage}, Details: {ex.Message} )"); if (extPubKey != null && ex.Message.StartsWith("Missing inputs", StringComparison.OrdinalIgnoreCase)) { Logs.Explorer.LogInformation($"{network.CryptoCode}: Trying to broadcast unconfirmed of the wallet"); var transactions = GetAnnotatedTransactions(repo, chain, extPubKey); foreach (var existing in transactions.UnconfirmedTransactions.Values) { try { await waiter.RPC.SendRawTransactionAsync(existing.Record.Transaction); } catch { } } try { await waiter.RPC.SendRawTransactionAsync(tx); Logs.Explorer.LogInformation($"{network.CryptoCode}: Broadcast success"); return(new BroadcastResult(true)); } catch (RPCException) { Logs.Explorer.LogInformation($"{network.CryptoCode}: Transaction {tx.GetHash()} failed to broadcast (Code: {ex.RPCCode}, Message: {ex.RPCCodeMessage}, Details: {ex.Message} )"); } } return(new BroadcastResult(false) { RPCCode = rpcEx.RPCCode, RPCCodeMessage = rpcEx.RPCCodeMessage, RPCMessage = rpcEx.Message }); } }
public static bool IsInsufficientFee(this RPCException ex) { return((int?)ex.RPCResult?.Error?.Code == -212); }
void p_OnClose(string error) { List <string> doomed; bool started; lock (state_lock) { closed_err = error ?? ""; started = this.started; doomed = new List <string> (pending.Keys); } foreach (var id in doomed) { ResolveRequest(id, started ? new RPCException("transport", "Connection lost") : new RPCException("transport", "Connection could not be established", RPCException.DispatchFailure()), null); } }
public override void Request(RequestLocalOptions opt, Message req, Action <Message> on_rpy) { string id; string is_closed; lock (state_lock) { id = (nextid++).ToString(); is_closed = closed_err; if (is_closed == null) { pending [id] = new RequestInfo { cb = on_rpy, timeout = new Timer((s) => { RequestTimedOut(id); }, null, (opt.Timeout + 5) * 1000, Timeout.Infinite), }; } } if (is_closed != null) { req.Discard(); Message.StreamToCallback(on_rpy, new RPCException("transport", "Connection is closed", RPCException.DispatchFailure()).AsHeader()); } else { req.Header ["request_id"] = id; req.Header ["type"] = "request"; p.SendMessage(req); } }
private static bool IsTransient(RPCException ex) { return(ex.Message.Contains("Loading wallet...") || ex.Message.Contains("Loading block index...") || ex.Message.Contains("Loading P2P addresses...")); }
public void InvalidCommandSendRPCException() { RPCException ex = Assert.Throws <RPCException>(() => this.rpcTestFixture.RpcClient.SendCommand("donotexist")); Assert.True(ex.RPCCode == RPCErrorCode.RPC_METHOD_NOT_FOUND); }
void ResolveRequest(string id, RPCException ex, Message rpy) { RequestInfo ri; lock (state_lock) { if (pending.TryGetValue (id, out ri)) pending.Remove (id); if (ri != null && ri.timeout != null) { ri.timeout.Dispose (); ri.timeout = null; } } if (ri == null) { if (rpy != null) rpy.Discard (); return; } if (ex != null) { Message.StreamToCallback (ri.cb, ex.AsHeader ()); } else { ri.cb (rpy); } }