Exemple #1
0
        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);
            }
        }
Exemple #2
0
        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.");
            }
        }
Exemple #3
0
        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);
                });
            });
        }
Exemple #4
0
        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.");
            }
        }
Exemple #5
0
        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.");
            }
        }
Exemple #6
0
        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.");
            }
        }
Exemple #7
0
 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..."));
 }
Exemple #8
0
        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
                });
            }
        }
Exemple #9
0
        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.");
            }
        }
Exemple #10
0
        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.");
            }
        }
Exemple #11
0
        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.");
            }
        }
Exemple #12
0
        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.");
            }
        }
Exemple #13
0
        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.");
            }
        }
Exemple #14
0
        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);
            }
        }
Exemple #15
0
        // 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);
        }
Exemple #16
0
 public static bool IsInsufficientToken(this RPCException ex)
 {
     return(ex.RPCResult.Error?.Code == RPCErrorCode.RPC_TYPE_ERROR &&
            ex.RPCResult.Error?.Message == "Sender has insufficient balance");
 }
Exemple #17
0
        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
                });
            }
        }
Exemple #18
0
 public static bool IsInsufficientFee(this RPCException ex)
 {
     return((int?)ex.RPCResult?.Error?.Code == -212);
 }
Exemple #19
0
        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);
            }
        }
Exemple #20
0
        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);
            }
        }
Exemple #21
0
 private static bool IsTransient(RPCException ex)
 {
     return(ex.Message.Contains("Loading wallet...") ||
            ex.Message.Contains("Loading block index...") ||
            ex.Message.Contains("Loading P2P addresses..."));
 }
Exemple #22
0
        public void InvalidCommandSendRPCException()
        {
            RPCException ex = Assert.Throws <RPCException>(() => this.rpcTestFixture.RpcClient.SendCommand("donotexist"));

            Assert.True(ex.RPCCode == RPCErrorCode.RPC_METHOD_NOT_FOUND);
        }
Exemple #23
0
        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);
            }
        }