public void FinishUnregisteredVar() { var txb = new TxBuilder(); var v = new WeaverVarAlias("test"); TestUtil.Throws <Exception>(() => txb.Finish(v)); }
public void GetVertex(bool pById) { const long id = 123456; const string expectScript = "_V0=g.V('" + DbName.Vert.Vertex.VertexId + "',_P0).next();"; IWeaverVarAlias <App> alias; var txb = new TxBuilder(); if (pById) { txb.GetVertex(id, out alias); } else { var app = new App(); app.VertexId = id; txb.GetVertex(app, out alias); } IWeaverQuery q = GetFirstQuery(txb); TestUtil.LogWeaverScript(Log, q); Assert.AreEqual(expectScript, q.Script, "Incorrect script."); TestUtil.CheckParams(q.Params, "_P", new List <object> { id }); }
public void AddVertex() { var vert = new Vertex(); vert.VertexId = 9876; vert.VertexType = 7; vert.Timestamp = 102030405060; IWeaverVarAlias <Vertex> alias; const string expectScript = "_V0=g.addVertex([" + DbName.Vert.Vertex.VertexId + ":_P0," + DbName.Vert.Vertex.Timestamp + ":_P1," + DbName.Vert.Vertex.VertexType + ":_P2" + "]);"; var txb = new TxBuilder(); txb.AddVertex(vert, out alias); txb.Finish(alias); //ensure that the alias becomes registered IWeaverQuery q = GetFirstQuery(txb); TestUtil.LogWeaverScript(Log, q); Assert.AreEqual(expectScript, q.Script, "Incorrect script."); TestUtil.CheckParams(q.Params, "_P", new List <object> { vert.VertexId, vert.Timestamp, vert.VertexType }); }
public void TestTxBuilder() { // Build the test Msg StdMsg message = new StdMsg(type: "cosmos-sdk/MsgSend", value: new Dictionary <String, Object> { { "from_address", "cosmos1huydeevpz37sd9snkgul6070mstupukw00xkw9" }, { "to_address", "cosmos12lla7fg3hjd2zj6uvf4pqj7atx273klc487c5k" }, { "amount", new List <StdCoin> { new StdCoin(denom: "uatom", amount: "100") } } }); // Read the expected test msg string from Test Resources (C# like - This is different from Dart approach) String expectedStrMsg = TestResources.SendStdTx; // Build the Msg List <StdMsg> msgList = new List <StdMsg> { message }; // Call the builder StdTx txMsg = TxBuilder.buildStdTx(msgList); // Get the String String strMsg = txMsg.ToString(); // Check it Assert.AreEqual(strMsg, expectedStrMsg); }
public void TestTxSigner() { List <String> mnemonic = new List <String>(singleVector.Split(" ", StringSplitOptions.RemoveEmptyEntries)); // Create the network info NetworkInfo networkInfo = new NetworkInfo(bech32Hrp: localbech32Hrp, lcdUrl: localTestUrl); // Build a transaction MsgSend msg = new MsgSend( fromAddress: "cosmos1hafptm4zxy5nw8rd2pxyg83c5ls2v62tstzuv2", toAddress: "cosmos12lla7fg3hjd2zj6uvf4pqj7atx273klc487c5k", amount: new List <StdCoin> { new StdCoin(denom: "uatom", amount: "100") } ); // Fee StdFee fee = new StdFee( gas: "200000", amount: new List <StdCoin> { new StdCoin(denom: "uatom", amount: "250") } ); StdTx tx = TxBuilder.buildStdTx(stdMsgs: new List <StdMsg> { msg }, fee: fee); // Create a wallet Wallet wallet = Wallet.derive(mnemonic, networkInfo); // Verify Wallet Assert.AreEqual(wallet.networkInfo.bech32Hrp, networkInfo.bech32Hrp); Assert.AreEqual(wallet.networkInfo.lcdUrl, networkInfo.lcdUrl); // Build the mockup server var _server = new MockHttpServer(); // I need this in order to get the correct data out of the mock server Dictionary <String, Object> accResponse = JsonConvert.DeserializeObject <Dictionary <String, Object> >(TestResources.AccountDataResponse); Dictionary <String, Object> NodeResponse = JsonConvert.DeserializeObject <Dictionary <String, Object> >(TestResources.NodeInfoResponse); // Initialize Server Response _server .WithService(localTestUrl) .Api("auth/accounts/{wallettAddress}", accResponse) .Api("node_info", NodeResponse); // Link the client to the retrieval classes HttpClient client = new HttpClient(_server); AccountDataRetrieval.client = client; NodeInfoRetrieval.client = client; // Call without await to avoid marking test class as async StdTx signedTx = TxSigner.signStdTx(wallet: wallet, stdTx: tx).Result; Assert.AreEqual(signedTx.signatures.Count, 1); StdSignature signature = (signedTx.signatures.ToArray())[0]; Assert.AreEqual(signature.publicKey.type, "tendermint/PubKeySecp256k1"); Assert.AreEqual(signature.publicKey.value, "ArMO2T5FNKkeF2aAZY012p/cpa9+PqKqw2GcQRPhAn3w"); Assert.AreEqual(signature.value, "m2op4CCBa39fRZD91WiqtBLKbUQI+1OWsc1tJkpDg+8FYB4y51KahGn26MskVMpTJl5gToIC1pX26hLbW1Kxrg=="); }
//////////////////////////////////////////////////////////////////////////////////////////////// /*--------------------------------------------------------------------------------------------*/ private IWeaverQuery GetFirstQuery(TxBuilder pTxBuild, int pExpectCount = 1) { Assert.NotNull(pTxBuild.Transaction, "Transaction should be filled."); Assert.NotNull(pTxBuild.Transaction.Queries, "Transaction.Queries should be filled."); Assert.AreEqual(pExpectCount, pTxBuild.Transaction.Queries.Count, "Incorrect Transaction.Queries count."); return(pTxBuild.Transaction.Queries[0]); }
/// Creates a transaction having the given [msgs] and [fee] inside, /// signs it with the given [Wallet] and sends it to the blockchain. /// Optional parameters can be [fee] and broadcasting [mode], /// that can be of type "sync", "async" or "block". public static async Task <TransactionResult> createSignAndSendTx(List <StdMsg> msgs, Wallet wallet, StdFee fee = null, BroadcastingMode mode = BroadcastingMode.SYNC) { if (fee == null) { // Set the default value for fee int msgsNumber = msgs.Count > 0 ? msgs.Count : 1; fee = GenericUtils.calculateDefaultFee(msgsNumber: msgsNumber, fee: defaultAmount, denom: defaultDenom, gas: defaultGas); } String modeStr = MyEnumExtensions.ToEnumMemberAttrValue(mode); StdTx stdTx = TxBuilder.buildStdTx(stdMsgs: msgs, fee: fee); StdTx signedTx = await TxSigner.signStdTx(wallet : wallet, stdTx : stdTx); // return await TxSender.broadcastStdTx(wallet: wallet, stdTx: signedTx, mode: modeStr); TransactionResult res = await TxSender.broadcastStdTx(wallet : wallet, stdTx : signedTx, mode : modeStr); return(res); }
public void Finish(bool pWithVar) { var txb = new TxBuilder(); Assert.Null(txb.Transaction.Script, "Script should be empty before Finish()."); if (pWithVar) { var v = new WeaverVarAlias("test"); txb.RegisterVarWithTxBuilder(v); txb.Finish(v); } else { txb.Finish(); } Assert.NotNull("", txb.Transaction.Script, "Script should be filled after Finish()."); }
public void AddEdgeUnregisteredVar(bool pFirst) { var edge = new ArtifactCreatedByMember(); var artAlias = new WeaverVarAlias <Artifact>("art"); var memAlias = new WeaverVarAlias <Member>("mem"); var txb = new TxBuilder(); if (pFirst) { txb.RegisterVarWithTxBuilder(artAlias); } else { txb.RegisterVarWithTxBuilder(memAlias); } TestUtil.Throws <Exception>(() => txb.AddEdge(artAlias, edge, memAlias)); }
public void GetVertexByDatabaseId(string pVarName) { const string id = "this-is-an-id"; string expectVarName = (pVarName ?? "_V0"); string expectScript = expectVarName + "=g.v(_P0);"; IWeaverVarAlias <App> alias; var app = new App(); app.Id = id; var txb = new TxBuilder(); txb.GetVertexByDatabaseId(app, out alias, pVarName); IWeaverQuery q = GetFirstQuery(txb); TestUtil.LogWeaverScript(Log, q); Assert.AreEqual(expectScript, q.Script, "Incorrect script."); TestUtil.CheckParams(q.Params, "_P", new List <object> { id }); }
public void AddEdge() { var edge = new ArtifactCreatedByMember(); var artAlias = new WeaverVarAlias <Artifact>("art"); var memAlias = new WeaverVarAlias <Member>("mem"); const string expectScript = "g.addEdge(art,mem,_P0);"; var txb = new TxBuilder(); txb.RegisterVarWithTxBuilder(artAlias); txb.RegisterVarWithTxBuilder(memAlias); txb.AddEdge(artAlias, edge, memAlias); IWeaverQuery q = GetFirstQuery(txb); TestUtil.LogWeaverScript(Log, q); Assert.AreEqual(expectScript, q.Script, "Incorrect script."); TestUtil.CheckParams(q.Params, "_P", new List <object> { DbName.Edge.ArtifactCreatedByMemberName }); }
static void Main(string[] args) { IConfiguration config = new ConfigurationBuilder() .AddJsonFile("appsettings.json", true, false) .AddJsonFile("appsettings.dev.json", true, true) .Build(); string signerHexStr = config["signer"]; if (string.IsNullOrWhiteSpace(signerHexStr)) { Console.WriteLine("Signer is not configured"); return; } string ip = config["bindIP"]; if (string.IsNullOrWhiteSpace(ip)) { Console.WriteLine("bindIP is not set.. defaulting to 127.0.0.1 local connection only"); ip = "127.0.0.1"; } using (var socket = new ResponseSocket()) { socket.Bind($"tcp://{ip}:55555"); while (true) { Console.WriteLine("running"); string requestString = socket.ReceiveFrameString(); string[] command = requestString.Split(); string response; if (command.Length < 2) { response = "poor"; Console.WriteLine(string.Empty); } else { var loader = new Loader <ICCGatewayPlugin>(); var msgs = new List <string>(); string root = Directory.GetCurrentDirectory(); string folder = TxBuilder.GetPluginsFolder(root); if (folder == null) { response = "fail"; } else { loader.Load(folder, msgs); foreach (var msg in msgs) { Console.WriteLine(msg); } string action = command[0]; command = command.Skip(1).ToArray(); ICCGatewayPlugin plugin = loader.Get(action); var pluginConfig = config.GetSection(action); if (plugin == null) { response = "miss"; } else { string msg; bool done = plugin.Run(pluginConfig, signerHexStr, command, out msg); if (done) { if (msg == null) { msg = "Success!"; } response = "good"; } else { response = "fail"; } } } } Console.WriteLine(response); socket.SendFrame(response); } } }
static void Main(string[] args) { IConfiguration config = new ConfigurationBuilder() .AddJsonFile("appsettings.json", true, false) .AddJsonFile("appsettings.dev.json", true, true) .Build(); string root = Directory.GetCurrentDirectory(); string folder = TxBuilder.GetPluginsFolder(root); if (folder == null) { Console.WriteLine("Failed to locate plugin folder"); return; } string ip = config["bindIP"]; if (string.IsNullOrWhiteSpace(ip)) { Console.WriteLine("bindIP is not set.. defaulting to 127.0.0.1 local connection only"); ip = "127.0.0.1"; } using (var socket = new ResponseSocket()) { socket.Bind($"tcp://{ip}:55555"); while (true) { string response; string requestString = null; try { requestString = socket.ReceiveFrameString(); string[] command = requestString.Split(); if (command.Length < 2) { response = "poor"; Console.WriteLine(requestString + ": not enough parameters"); } else { var loader = new Loader <ICCGatewayPlugin>(); var msgs = new List <string>(); loader.Load(folder, msgs); foreach (var msg in msgs) { Console.WriteLine(msg); } string action = command[0]; command = command.Skip(1).ToArray(); ICCGatewayPlugin plugin = loader.Get(action); var pluginConfig = config.GetSection(action); if (plugin == null) { response = "miss"; } else { string msg; bool done = plugin.Run(pluginConfig, command, out msg); if (done) { Debug.Assert(msg == null); response = "good"; } else { Debug.Assert(msg != null); StringBuilder err = new StringBuilder(); err.Append(requestString).Append(": ").Append(msg); Console.WriteLine(err.ToString()); response = "fail"; } } } } catch (Exception x) { StringBuilder err = new StringBuilder(); if (requestString != null) { err.Append(requestString).Append(": "); } err.Append(x.Message); Console.WriteLine(err.ToString()); response = "fail"; } socket.SendFrame(response); } } }
private const int SKIP_TO_GET_60 = 512 / 8 * 2 - 60; // 512 - hash size, 8 - bits in byte, 2 - hex digits for byte, 60 - merkle address length (70) without namespace length (6) and prexix length (4) static void Main(string[] args) { try { IConfiguration config = new ConfigurationBuilder() .AddJsonFile("appsettings.json", true, false) #if DEBUG .AddJsonFile("appsettings.dev.json", true, false) #endif .Build(); string signerHexStr = config["signer"]; if (string.IsNullOrWhiteSpace(signerHexStr)) { Console.WriteLine("Signer is not configured"); return; } var signer = new Signer(RpcHelper.HexToBytes(signerHexStr)); string creditcoinRestApiURL = config["creditcoinRestApiURL"]; if (!string.IsNullOrWhiteSpace(creditcoinRestApiURL)) { creditcoinUrl = creditcoinRestApiURL; } string root = Directory.GetCurrentDirectory(); string folder = TxBuilder.GetPluginsFolder(root); if (folder == null) { Console.WriteLine("plugins subfolder not found"); return; } string progress = Path.Combine(folder, "progress.txt"); string action; string[] command; if (File.Exists(progress)) { Console.WriteLine("Found unfinished action, retrying..."); args = File.ReadAllText(progress).Split(); } else { File.WriteAllText(progress, string.Join(' ', args)); } action = args[0].ToLower(); command = args.Skip(1).ToArray(); var txBuilder = new TxBuilder(signer); var settings = new Dictionary <string, string>(); filter(settingNamespace, (string address, byte[] protobuf) => { Setting setting = Setting.Parser.ParseFrom(protobuf); foreach (var entry in setting.Entries) { settings.Add(entry.Key, entry.Value); } }); bool inProgress = false; // API: // list Settings|Wallets|Addresses|Transfers|AskOrders|BidOrders|DealOrders|RepaymentOrders| // list Balance // list Sighash // list Address blockchain address // list UnusedTransfers addressId amount // list MatchingOrders // list CreditHistory sighash // list NewDeals // list RunningDeals // list NewRepaymentOrders // creditcoin AddFunds amount sighash (creditcoin AddFunds 1000000 16de574ac8ac3067977df056ecff51345672d25d528303b3555ab2aa4cd5) // AddFunds only works for a registered signer // creditcoin SendFunds amount sighash (creditcoin SendFunds 200000 8704a4f77befea5c8082d414f98dc16e4ba82a0898422d031f41693260a0) // creditcoin RegisterAddress blockchain address (creditcoin RegisterAddress bitcoin <BITCOIN-ADDRESS>) // creditcoin AddAskOrder blockchain amount interest blockchain collateral fee expiration capitalLockTransferId (creditcoin AddAskOrder bitcoin 1000000 10 bitcoin 50 100 1565386152 <TRANSFER-ID>) // creditcoin AddBidOrder blockchain amount interest blockchain collateral fee expiration (creditcoin AddAskOrder bitcoin 1000000 10 bitcoin 50 100 1565386152) // creditcoin AddDealOrder askOrderId bidOrderId // creditcoin CompleteDealOrder dealOrderId collateralLockTransferId // creditcoin AddRepaymentOrder dealOrderId // creditcoin CompleteRepaymentOrder repaymentOrderId transferId // creditcoin CollectCoins transferId // <blockchain> RegisterTransfer ... // bitcoin RegisterTransfer registeredAddressId amount sourceTxId // ethereum RegisterTransfer registeredAddressId amount [erc20] // unlock Funds dealOrderId addressToUnlockFundsTo // unlock Collateral repaymentOrderId addressToUnlockCollateralTo if (action.Equals("unlock")) { string externalGatewayAddress; if (!settings.TryGetValue("sawtooth.validator.gateway", out externalGatewayAddress)) { Console.WriteLine("Error: external gateway is not configured"); } else { if (!externalGatewayAddress.StartsWith("tcp://")) { externalGatewayAddress = "tcp://" + externalGatewayAddress; } bool success = true; switch (command[0].ToLower()) { case "funds": Debug.Assert(command.Length == 3); { var dealOrderId = command[1].ToLower(); var addressToUnlockFundsTo = command[2].ToLower(); string msg; string blockchain = null; var protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{dealOrderId}", out msg); if (protobuf != null) { var dealOrder = DealOrder.Parser.ParseFrom(protobuf); protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{dealOrder.AskOrderId}", out msg); if (protobuf != null) { var askOrder = AskOrder.Parser.ParseFrom(protobuf); blockchain = askOrder.Blockchain; } } if (blockchain == null) { success = false; Console.WriteLine("Error: " + msg); } else { string escrow; if (!settings.TryGetValue("sawtooth.escrow." + blockchain, out escrow)) { success = false; Console.WriteLine("Error: escrow is not configured for " + blockchain); } else { using (var socket = new RequestSocket()) { socket.Connect(externalGatewayAddress); var request = $"{blockchain} unlock funds {escrow} {dealOrderId} {addressToUnlockFundsTo}"; socket.SendFrame(request); string response = socket.ReceiveFrameString(); if (response != "good") { success = false; Console.WriteLine("Error: failed to execute the global gateway command"); } } } } } break; case "collateral": Debug.Assert(command.Length == 3); { var repaymentOrderId = command[1].ToLower(); var addressToUnlockCollateralsTo = command[2].ToLower(); string msg; string blockchain = null; var protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{repaymentOrderId}", out msg); if (protobuf != null) { var repaymentOrder = RepaymentOrder.Parser.ParseFrom(protobuf); protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{repaymentOrder.DealId}", out msg); if (protobuf != null) { var dealOrder = DealOrder.Parser.ParseFrom(protobuf); protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{dealOrder.AskOrderId}", out msg); if (protobuf != null) { var askOrder = AskOrder.Parser.ParseFrom(protobuf); blockchain = askOrder.Blockchain; } } } if (blockchain == null) { success = false; Console.WriteLine("Error: " + msg); } else { string escrow; if (!settings.TryGetValue("sawtooth.escrow." + blockchain, out escrow)) { success = false; Console.WriteLine("Error: escrow is not configured for " + blockchain); } else { using (var socket = new RequestSocket()) { socket.Connect(externalGatewayAddress); var request = $"{blockchain} unlock collateral {escrow} {repaymentOrderId} {addressToUnlockCollateralsTo}"; socket.SendFrame(request); string response = socket.ReceiveFrameString(); if (response != "good") { success = false; Console.WriteLine("Error: failed to execute the global gateway command"); } } } } } break; } if (success) { Console.WriteLine("Success"); } } } else if (action.Equals("list")) { bool success = true; if (command[0].Equals("settings", StringComparison.OrdinalIgnoreCase)) { Debug.Assert(command.Length == 1); filter(settingNamespace, (string objid, byte[] protobuf) => { Setting setting = Setting.Parser.ParseFrom(protobuf); foreach (var entry in setting.Entries) { Console.WriteLine($"{entry.Key}: {entry.Value}"); } }); } else if (command[0].Equals("wallets", StringComparison.OrdinalIgnoreCase)) { Debug.Assert(command.Length == 1); filter(creditCoinNamespace + walletPrefix, (string objid, byte[] protobuf) => { Wallet wallet = Wallet.Parser.ParseFrom(protobuf); Console.WriteLine($"wallet({objid}) amount:{wallet.Amount}"); }); } else if (command[0].Equals("balance", StringComparison.OrdinalIgnoreCase)) { Debug.Assert(command.Length == 1); { string sighash = sha256(signer.GetPublicKey().ToHexString()); string prefix = creditCoinNamespace + walletPrefix; string id = prefix + sighash; filter(prefix, (string objid, byte[] protobuf) => { Wallet wallet = Wallet.Parser.ParseFrom(protobuf); if (objid.Equals(id)) { Console.WriteLine($"balance for {sighash} is {wallet.Amount}"); } }); } } else if (command[0].Equals("addresses", StringComparison.OrdinalIgnoreCase)) { Debug.Assert(command.Length == 1); filter(creditCoinNamespace + addressPrefix, (string objid, byte[] protobuf) => { Address address = Address.Parser.ParseFrom(protobuf); Console.WriteLine($"address({objid}) sighash:{address.Sighash}, blockchain: {address.Blockchain}, address:{address.Address_}"); }); } else if (command[0].Equals("transfers", StringComparison.OrdinalIgnoreCase)) { Debug.Assert(command.Length == 1); filter(creditCoinNamespace + transferPrefix, (string objid, byte[] protobuf) => { Transfer transfer = Transfer.Parser.ParseFrom(protobuf); Console.WriteLine($"transfer({objid}) sighash:{transfer.Sighash}, blockchain: {transfer.Blockchain}, amount:{transfer.Amount}, fee:{transfer.Fee}, txid:{transfer.Txid}"); }); } else if (command[0].Equals("askOrders", StringComparison.OrdinalIgnoreCase)) { Debug.Assert(command.Length == 1); filter(creditCoinNamespace + askOrderPrefix, (string objid, byte[] protobuf) => { AskOrder askOrder = AskOrder.Parser.ParseFrom(protobuf); Console.WriteLine($"askOrder({objid}) sighash:{askOrder.Sighash}, blockchain: {askOrder.Blockchain}, amount:{askOrder.Amount}, interest:{askOrder.Interest}, collateralBlockchain:{askOrder.CollateralBlockchain}, collateral:{askOrder.Collateral}, fee:{askOrder.Fee}, expiration:{askOrder.Expiration}, transferId:{askOrder.TransferId}"); }); } else if (command[0].Equals("bidOrders", StringComparison.OrdinalIgnoreCase)) { Debug.Assert(command.Length == 1); filter(creditCoinNamespace + bidOrderPrefix, (string objid, byte[] protobuf) => { BidOrder bidOrder = BidOrder.Parser.ParseFrom(protobuf); Console.WriteLine($"bidOrder({objid}) sighash:{bidOrder.Sighash}, blockchain: {bidOrder.Blockchain}, amount:{bidOrder.Amount}, interest:{bidOrder.Interest}, collateralBlockchain:{bidOrder.CollateralBlockchain}, collateral:{bidOrder.Collateral}, fee:{bidOrder.Fee}, expiration:{bidOrder.Expiration}"); }); } else if (command[0].Equals("dealOrders", StringComparison.OrdinalIgnoreCase)) { Debug.Assert(command.Length == 1); filter(creditCoinNamespace + dealOrderPrefix, (string objid, byte[] protobuf) => { DealOrder dealOrder = DealOrder.Parser.ParseFrom(protobuf); Console.WriteLine($"dealOrder({objid}) askOrderId:{dealOrder.AskOrderId}, bidOrderId: {dealOrder.BidOrderId}, collateralTransferId:{dealOrder.CollateralTransferId}"); }); } else if (command[0].Equals("repaymentOrders", StringComparison.OrdinalIgnoreCase)) { Debug.Assert(command.Length == 1); filter(creditCoinNamespace + repaymentOrderPrefix, (string objid, byte[] protobuf) => { RepaymentOrder repaymentOrder = RepaymentOrder.Parser.ParseFrom(protobuf); Console.WriteLine($"repaymentOrder({objid}) dealId:{repaymentOrder.DealId}, transferId:{repaymentOrder.TransferId}"); }); } else if (command[0].Equals("sighash", StringComparison.OrdinalIgnoreCase)) { Console.WriteLine(sha256(signer.GetPublicKey().ToHexString())); } else if (command[0].Equals("address", StringComparison.OrdinalIgnoreCase)) { Debug.Assert(command.Length == 3); var blockchain = command[1].ToLower(); var addr = command[2]; filter(creditCoinNamespace + addressPrefix, (string objid, byte[] protobuf) => { Address address = Address.Parser.ParseFrom(protobuf); if (address.Blockchain == blockchain && address.Address_ == addr) { Console.WriteLine(objid); } }); } else if (command[0].Equals("unusedTransfers", StringComparison.OrdinalIgnoreCase)) { Debug.Assert(command.Length == 3); var addressId = command[1]; var amount = command[2]; var sighash = sha256(signer.GetPublicKey().ToHexString()); Address address = null; filter(creditCoinNamespace + addressPrefix, (string objid, byte[] protobuf) => { if (objid == addressId) { address = Address.Parser.ParseFrom(protobuf); } }); if (address == null) { Console.WriteLine("Invalid command " + command[0]); success = false; } else { filter(creditCoinNamespace + transferPrefix, (string objid, byte[] protobuf) => { Transfer transfer = Transfer.Parser.ParseFrom(protobuf); if (transfer.Sighash == sighash && transfer.Orderid.Equals(string.Empty) && transfer.Blockchain == address.Blockchain && transfer.Amount == amount) { Console.WriteLine(objid); } }); } } else if (command[0].Equals("matchingOrders", StringComparison.OrdinalIgnoreCase)) { Debug.Assert(command.Length == 1); var askOrders = new Dictionary <string, AskOrder>(); filter(creditCoinNamespace + askOrderPrefix, (string objid, byte[] protobuf) => { AskOrder askOrder = AskOrder.Parser.ParseFrom(protobuf); askOrders.Add(objid, askOrder); }); var bidOrders = new Dictionary <string, BidOrder>(); filter(creditCoinNamespace + bidOrderPrefix, (string objid, byte[] protobuf) => { BidOrder bidOrder = BidOrder.Parser.ParseFrom(protobuf); bidOrders.Add(objid, bidOrder); }); match(signer, askOrders, bidOrders); } else if (command[0].Equals("creditHistory", StringComparison.OrdinalIgnoreCase)) { Debug.Assert(command.Length == 2); var fundraiser = command[1].ToLower(); filterDeals(null, fundraiser, (string dealAddress, DealOrder dealOrder, AskOrder askOrder, BidOrder bidOrder) => { Debug.Assert(askOrder == null); var status = dealOrder.CollateralTransferId.Equals(string.Empty) ? "INCOMPLETE" : "COMPLETE"; if (!dealOrder.UnlockCollateralDestinationAddressId.Equals(string.Empty)) { status = "CLOSED"; } else if (!dealOrder.UnlockFundsDestinationAddressId.Equals(string.Empty)) { status = "ACTIVE"; } Console.WriteLine($"status: {status}, amount:{bidOrder.Amount}, blockchain: {bidOrder.Blockchain}, collateral:{bidOrder.Collateral}"); }); } else if (command[0].Equals("newDeals", StringComparison.OrdinalIgnoreCase)) { Debug.Assert(command.Length == 1); var fundraiser = sha256(signer.GetPublicKey().ToHexString()); filterDeals(null, fundraiser, (string dealAddress, DealOrder dealOrder, AskOrder askOrder, BidOrder bidOrder) => { Debug.Assert(askOrder == null); if (dealOrder.CollateralTransferId.Equals(string.Empty)) { Console.WriteLine(dealAddress); } }); } else if (command[0].Equals("runningDeals", StringComparison.OrdinalIgnoreCase)) { Debug.Assert(command.Length == 1); var investor = sha256(signer.GetPublicKey().ToHexString()); var deals = new List <string>(); filterDeals(investor, null, (string dealAddress, DealOrder dealOrder, AskOrder askOrder, BidOrder bidOrder) => { Debug.Assert(bidOrder == null); if (!dealOrder.CollateralTransferId.Equals(string.Empty) && dealOrder.UnlockCollateralDestinationAddressId.Equals(string.Empty)) { deals.Add(dealAddress); } }); filter(creditCoinNamespace + repaymentOrderPrefix, (string objid, byte[] protobuf) => { RepaymentOrder repaymentOrder = RepaymentOrder.Parser.ParseFrom(protobuf); if (deals.SingleOrDefault(x => x.Equals(repaymentOrder.DealId)) != null) { deals.Remove(repaymentOrder.DealId); } }); foreach (var deal in deals) { Console.WriteLine(deal); } } else if (command[0].Equals("newRepaymentOrders", StringComparison.OrdinalIgnoreCase)) { Debug.Assert(command.Length == 1); var fundraiser = sha256(signer.GetPublicKey().ToHexString()); var deals = new List <string>(); filterDeals(null, fundraiser, (string dealAddress, DealOrder dealOrder, AskOrder askOrder, BidOrder bidOrder) => { Debug.Assert(askOrder == null); if (!dealOrder.CollateralTransferId.Equals(string.Empty) && dealOrder.UnlockCollateralDestinationAddressId.Equals(string.Empty)) { deals.Add(dealAddress); } }); filter(creditCoinNamespace + repaymentOrderPrefix, (string objid, byte[] protobuf) => { RepaymentOrder repaymentOrder = RepaymentOrder.Parser.ParseFrom(protobuf); if (repaymentOrder.TransferId.Equals(string.Empty) && deals.SingleOrDefault(x => x.Equals(repaymentOrder.DealId)) != null) { Console.WriteLine(objid); } }); } else { Console.WriteLine("Invalid command " + command[0]); success = false; } if (success) { Console.WriteLine("Success"); } } else if (action.Equals("creditcoin")) { string msg; var tx = txBuilder.BuildTx(command, out msg); if (tx == null) { Debug.Assert(msg != null); Console.WriteLine(msg); } else { Debug.Assert(msg == null); var content = new ByteArrayContent(tx); content.Headers.Add("Content-Type", "application/octet-stream"); Console.WriteLine(RpcHelper.CompleteBatch(httpClient, $"{creditcoinUrl}/batches", content)); } } else { var loader = new Loader <ICCClientPlugin>(); var msgs = new List <string>(); loader.Load(folder, msgs); foreach (var msg in msgs) { Console.WriteLine(msg); } ICCClientPlugin plugin = loader.Get(action); var pluginConfig = config.GetSection(action); if (plugin == null) { Console.WriteLine("Error: Unknown action " + action); } else { string msg; bool done = plugin.Run(pluginConfig, httpClient, txBuilder, settings, folder, creditcoinUrl, command, out inProgress, out msg); if (done) { if (msg == null) { msg = "Success"; } Console.WriteLine(msg); } else { Console.WriteLine("Error: " + msg); } } } if (!inProgress) { File.Delete(progress); } } catch (Exception x) { Console.WriteLine($"Error: unexpected failure - {x.Message}"); } }
public async Task test_broadcastStdTx() { //This is the comparison class CompareLogic compareLogic = new CompareLogic(); NetworkInfo networkInfo = new NetworkInfo(bech32Hrp: "did:com:", lcdUrl: "http://localhost:1317"); //primo mnemonic String mnemonicString1 = "gorilla soldier device force cupboard transfer lake series cement another bachelor fatigue royal lens juice game sentence right invite trade perfect town heavy what"; List <String> mnemonic = new List <String>(mnemonicString1.Split(" ", StringSplitOptions.RemoveEmptyEntries)); //secondo mnemonic String mnemonicString2 = "daughter conduct slab puppy horn wrap bone road custom acoustic adjust target price trip unknown agent infant proof whip picnic exact hobby phone spin"; List <String> mnemonic2 = new List <String>(mnemonicString2.Split(" ", StringSplitOptions.RemoveEmptyEntries)); Wallet wallet = Wallet.derive(mnemonic, networkInfo); Wallet recipientWallet = Wallet.derive(mnemonic2, networkInfo); List <StdCoin> depositAmount = new List <StdCoin> { new StdCoin(denom: "ucommercio", amount: "10000") }; var dict = new Dictionary <string, object>(); dict.Add("from_address", wallet.bech32Address); dict.Add("to_address", recipientWallet.bech32Address); dict.Add("amount", depositAmount); StdMsg testmsg = new StdMsg("cosmos-sdk/MsgSend", dict); List <StdMsg> Listtestmsg = new List <StdMsg>(); Listtestmsg.Add(testmsg); StdFee fee = new StdFee(depositAmount, "200000"); //Invio try { var stdTx = TxBuilder.buildStdTx(Listtestmsg, "", fee); var signedStdTx = await TxSigner.signStdTx(wallet : wallet, stdTx : stdTx); var result = await TxSender.broadcastStdTx(wallet : wallet, stdTx : signedStdTx); if (result.success) { Console.WriteLine("Tx send successfully:\n$lcdUrl/txs/${result.hash}"); } else { Console.WriteLine("Tx error message:\n${result.error?.errorMessage}"); } } catch (Exception ex) { Console.WriteLine("Error while testing Sacco:\n$error"); } }
public bool Run(IConfiguration cfg, string signerHexStr, string[] command, out string msg) { Debug.Assert(command != null); Debug.Assert(command.Length > 0); if (command[0].Equals("verify")) { Debug.Assert(command.Length == 7); string txId = command[1]; string destinationAddressString = command[2]; string destinationAmount = command[3]; string sighash = command[4]; string sourceAddressString = command[5]; string networkId = command[6]; // TODO disable confirmation count config for release build string confirmationsCount = cfg["confirmationsCount"]; if (string.IsNullOrWhiteSpace(confirmationsCount)) { msg = "ethereum.confirmationsCount is not set"; return(false); } if (!int.TryParse(confirmationsCount, out int confirmationsExpected)) { msg = "ethereum.confirmationsCount is not an int"; return(false); } string rpcUrl = cfg["rpc"]; if (string.IsNullOrWhiteSpace(rpcUrl)) { msg = "ethereum.rpc is not set"; return(false); } var web3 = new Nethereum.Web3.Web3(rpcUrl); var tx = web3.Eth.Transactions.GetTransactionByHash.SendRequestAsync(txId).Result; int confirmations = 0; if (tx.BlockNumber != null) { var blockNumber = web3.Eth.Blocks.GetBlockNumber.SendRequestAsync().Result; confirmations = (int)(blockNumber.Value - tx.BlockNumber.Value); } if (confirmations < confirmationsExpected) { msg = "Invalid transaction: not enough confirmations"; return(false); } if (!sourceAddressString.Equals(tx.From, System.StringComparison.OrdinalIgnoreCase)) { msg = "Invalid transaction: wrong sourceAddressString"; return(false); } if (networkId.Equals("creditcoin")) { string creditcoinContract = cfg["creditcoinContract"]; if (string.IsNullOrWhiteSpace(creditcoinContract)) { msg = "ethereum.creditcoinContract is not set"; return(false); } string creditcoinContractAbi = cfg["creditcoinContractAbi"]; if (string.IsNullOrWhiteSpace(creditcoinContractAbi)) { msg = "ethereum.creditcoinContractAbi is not set"; return(false); } var contract = web3.Eth.GetContract(creditcoinContractAbi, creditcoinContract); var burn = contract.GetFunction("exchange"); var inputs = burn.DecodeInput(tx.Input); Debug.Assert(inputs.Count == 2); var value = inputs[0].Result.ToString(); if (destinationAmount != value) { msg = "Invalid transaction: wrong amount"; return(false); } var tag = inputs[1].Result.ToString(); if (!tag.Equals(sighash)) { msg = "Invalid transaction: wrong sighash"; return(false); } } else { if (destinationAmount != tx.Value.Value.ToString()) { msg = "Invalid transaction: wrong amount"; return(false); } if (tx.Input == null) { msg = "Invalid transaction: expecting data"; return(false); } if (!sighash.StartsWith("0x")) { sighash = "0x" + sighash; } if (!tx.Input.Equals(sighash, System.StringComparison.OrdinalIgnoreCase)) { msg = "Invalid transaction: wrong sighash"; return(false); } if (!tx.To.Equals(destinationAddressString, System.StringComparison.OrdinalIgnoreCase)) { msg = "Invalid transaction: wrong destinationAddressString"; return(false); } } msg = null; return(true); } else if (command[0].Equals("unlock")) { var ccSigner = new Signer(RpcHelper.HexToBytes(signerHexStr)); var txBuilder = new TxBuilder(ccSigner); Debug.Assert(command.Length == 5); string kind = command[1]; string addressFromString = command[2]; HttpClient httpClient = new HttpClient(); string txFrom; string amountString; string feeString; string addressToString; string networkId; string ccCommand; if (kind.Equals("funds")) { string dealOrderId = command[3]; string addressToUnlockFundsTo = command[4]; var protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{dealOrderId}", out msg); if (protobuf == null) { return(false); } var dealOrder = DealOrder.Parser.ParseFrom(protobuf); protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{dealOrder.AskOrderId}", out msg); if (protobuf == null) { return(false); } var askOrder = AskOrder.Parser.ParseFrom(protobuf); protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{askOrder.TransferId}", out msg); if (protobuf == null) { return(false); } var transfer = Transfer.Parser.ParseFrom(protobuf); protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{addressToUnlockFundsTo}", out msg); if (protobuf == null) { return(false); } var address = Address.Parser.ParseFrom(protobuf); if (!askOrder.Sighash.Equals(address.Sighash)) { msg = "The address doesn't match the ask order"; return(false); } txFrom = transfer.Txid; amountString = transfer.Amount; feeString = transfer.Fee; addressToString = address.Address_; networkId = transfer.Network; ccCommand = "UnlockFunds"; } else if (kind.Equals("collateral")) { string repaymentOrderId = command[3]; string addressToUnlockCollateralsTo = command[4]; var protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{repaymentOrderId}", out msg); if (protobuf == null) { return(false); } var repaymentOrder = RepaymentOrder.Parser.ParseFrom(protobuf); protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{repaymentOrder.DealId}", out msg); if (protobuf == null) { return(false); } var dealOrder = DealOrder.Parser.ParseFrom(protobuf); protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{dealOrder.AskOrderId}", out msg); if (protobuf == null) { return(false); } var askOrder = AskOrder.Parser.ParseFrom(protobuf); protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{askOrder.TransferId}", out msg); if (protobuf == null) { return(false); } var transfer = Transfer.Parser.ParseFrom(protobuf); protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{addressToUnlockCollateralsTo}", out msg); if (protobuf == null) { return(false); } var address = Address.Parser.ParseFrom(protobuf); if (!askOrder.Sighash.Equals(address.Sighash)) { msg = "The address doesn't match the ask order"; return(false); } txFrom = transfer.Txid; amountString = transfer.Amount; feeString = transfer.Fee; addressToString = address.Address_; networkId = transfer.Network; ccCommand = "UnlockCollateral"; } else { msg = "unknown unlock kind"; return(false); } string secret = cfg["secret"]; if (string.IsNullOrWhiteSpace(secret)) { msg = "ethereum.secret is not set"; return(false); } var ethereumPrivateKey = secret; // TODO disable confirmation count config for release build string confirmationsCount = cfg["confirmationsCount"]; if (string.IsNullOrWhiteSpace(confirmationsCount)) { msg = "ethereum.confirmationsCount is not set"; return(false); } if (!int.TryParse(confirmationsCount, out int confirmationsExpected)) { msg = "ethereum.confirmationsCount is not an int"; return(false); } string rpcUrl = cfg["rpc"]; if (string.IsNullOrWhiteSpace(rpcUrl)) { msg = "ethereum.rpc is not set"; return(false); } BigInteger fee; if (!BigInteger.TryParse(feeString, out fee)) { msg = "Invalid progress data"; return(false); } var web3 = new Nethereum.Web3.Web3(rpcUrl); BigInteger transferAmount; if (!BigInteger.TryParse(amountString, out transferAmount) || transferAmount <= 0) { msg = "Invalid amount"; return(false); } string sourceAddress = EthECKey.GetPublicAddress(ethereumPrivateKey); if (!sourceAddress.Equals(addressFromString, StringComparison.OrdinalIgnoreCase)) { msg = "The deal is for a different client"; return(false); } var txCount = web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(sourceAddress).Result; TransactionSigner signer = new TransactionSigner(); var gasLimit = web3.Eth.Transactions.EstimateGas.SendRequestAsync(new Nethereum.RPC.Eth.DTOs.CallInput(string.Empty, addressToString, new Nethereum.Hex.HexTypes.HexBigInteger(transferAmount))).Result; var gasPrice = web3.Eth.GasPrice.SendRequestAsync().Result; string txRaw = signer.SignTransaction(ethereumPrivateKey, addressToString, transferAmount + fee, txCount, gasPrice, gasLimit, string.Empty); string payTxId = web3.Eth.Transactions.SendRawTransaction.SendRequestAsync("0x" + txRaw).Result; while (true) { var receipt = web3.Eth.TransactionManager.TransactionReceiptService.PollForReceiptAsync(payTxId).Result; if (receipt.BlockNumber != null) { var blockNumber = web3.Eth.Blocks.GetBlockNumber.SendRequestAsync().Result; if (blockNumber.Value - receipt.BlockNumber.Value >= confirmationsExpected) { break; } } Thread.Sleep(1000); } command = new string[] { ccCommand, command[3], command[4] }; var tx = txBuilder.BuildTx(command, out msg); Debug.Assert(tx != null); Debug.Assert(msg == null); var content = new ByteArrayContent(tx); content.Headers.Add("Content-Type", "application/octet-stream"); msg = RpcHelper.CompleteBatch(httpClient, $"{creditcoinUrl}/batches", content); } msg = "Unknown command: " + command[0]; return(false); }
public bool Run(IConfiguration cfg, string signerHexStr, string[] command, out string msg) { Debug.Assert(command != null); Debug.Assert(command.Length > 0); if (command[0].Equals("verify")) { Debug.Assert(command.Length == 7); string txId = command[1]; string destinationAdressString = command[2]; string destinationAmount = command[3]; string sighash = command[4]; string sourceAddressString = command[5]; string networkId = command[6]; string rpcAddress = cfg["rpc"]; if (string.IsNullOrWhiteSpace(rpcAddress)) { msg = "bitcoin.rpc is not set"; return(false); } string credential = cfg["credential"]; if (string.IsNullOrWhiteSpace(credential)) { msg = "bitcoin.credential is not set"; return(false); } // TODO disable confirmation customization for release build string confirmationsCount = cfg["confirmationsCount"]; if (string.IsNullOrWhiteSpace(confirmationsCount)) { msg = "bitcoin.confirmationsCount is not set"; return(false); } var confirmationsExpected = 1; if (!int.TryParse(confirmationsCount, out confirmationsExpected)) { msg = "bitcoin.confirmationsCount is not an int"; return(false); } Network network = ((networkId == "1") ? Network.Main : Network.TestNet); var rpcClient = new RPCClient(credential, new Uri(rpcAddress), network); if (!uint256.TryParse(txId, out var transactionId)) { msg = "Invalid transaction: transaction ID invalid"; return(false); } var transactionInfoResponse = rpcClient.GetRawTransactionInfo(transactionId); if (transactionInfoResponse.Confirmations < confirmationsExpected) { msg = "Invalid transaction: not enough confirmations"; return(false); } if (transactionInfoResponse.Transaction.Outputs.Count < 2 || transactionInfoResponse.Transaction.Outputs.Count > 3) { msg = "Invalid transaction: unexpected amount of output"; return(false); } var destinationAddress = BitcoinAddress.Create(destinationAdressString, network); var outputCoins = transactionInfoResponse.Transaction.Outputs.AsCoins(); var paymentCoin = outputCoins.SingleOrDefault(oc => oc.ScriptPubKey == destinationAddress.ScriptPubKey); if (paymentCoin == null) { msg = "Invalid transaction: wrong destinationAdressString"; return(false); } if (paymentCoin.TxOut.Value.Satoshi.ToString() != destinationAmount.ToString()) { msg = "Invalid transaction: wrong amount"; return(false); } var bytes = Encoding.UTF8.GetBytes(sighash); var nullDataCoin = outputCoins.SingleOrDefault(oc => oc.ScriptPubKey == TxNullDataTemplate.Instance.GenerateScriptPubKey(bytes)); if (nullDataCoin == null) { msg = "Invalid transaction: wrong sighash"; return(false); } if (nullDataCoin.TxOut.Value.CompareTo(Money.Zero) != 0) { msg = "Invalid transaction: expecting a message"; return(false); } var sourceAddress = BitcoinAddress.Create(sourceAddressString, network); var input = transactionInfoResponse.Transaction.Inputs[0]; if (!Script.VerifyScript(input.ScriptSig, sourceAddress.ScriptPubKey, transactionInfoResponse.Transaction, 0)) { msg = "Invalid transaction: wrong sourceAddressString"; return(false); } msg = null; return(true); } else if (command[0].Equals("unlock")) { var ccSigner = new Signer(RpcHelper.HexToBytes(signerHexStr)); var txBuilder = new TxBuilder(ccSigner); Debug.Assert(command.Length == 5); string kind = command[1]; string addressFromString = command[2]; HttpClient httpClient = new HttpClient(); string txFrom; string amountString; string feeString; string addressToString; string networkId; string ccCommand; if (kind.Equals("funds")) { string dealOrderId = command[3]; string addressToUnlockFundsTo = command[4]; var protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{dealOrderId}", out msg); if (protobuf == null) { return(false); } var dealOrder = DealOrder.Parser.ParseFrom(protobuf); protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{dealOrder.AskOrderId}", out msg); if (protobuf == null) { return(false); } var askOrder = AskOrder.Parser.ParseFrom(protobuf); protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{askOrder.TransferId}", out msg); if (protobuf == null) { return(false); } var transfer = Transfer.Parser.ParseFrom(protobuf); protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{addressToUnlockFundsTo}", out msg); if (protobuf == null) { return(false); } var address = Address.Parser.ParseFrom(protobuf); if (!askOrder.Sighash.Equals(address.Sighash)) { msg = "The adress doesn't match the ask order"; return(false); } txFrom = transfer.Txid; amountString = transfer.Amount; feeString = transfer.Fee; addressToString = address.Address_; networkId = transfer.Network; ccCommand = "UnlockFunds"; } else if (kind.Equals("collateral")) { string repaymentOrderId = command[3]; string addressToUnlockCollateralsTo = command[4]; var protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{repaymentOrderId}", out msg); if (protobuf == null) { return(false); } var repaymentOrder = RepaymentOrder.Parser.ParseFrom(protobuf); protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{repaymentOrder.DealId}", out msg); if (protobuf == null) { return(false); } var dealOrder = DealOrder.Parser.ParseFrom(protobuf); protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{dealOrder.AskOrderId}", out msg); if (protobuf == null) { return(false); } var askOrder = AskOrder.Parser.ParseFrom(protobuf); protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{askOrder.TransferId}", out msg); if (protobuf == null) { return(false); } var transfer = Transfer.Parser.ParseFrom(protobuf); protobuf = RpcHelper.ReadProtobuf(httpClient, $"{creditcoinUrl}/state/{addressToUnlockCollateralsTo}", out msg); if (protobuf == null) { return(false); } var address = Address.Parser.ParseFrom(protobuf); if (!askOrder.Sighash.Equals(address.Sighash)) { msg = "The adress doesn't match the ask order"; return(false); } txFrom = transfer.Txid; amountString = transfer.Amount; feeString = transfer.Fee; addressToString = address.Address_; networkId = transfer.Network; ccCommand = "UnlockCollateral"; } else { msg = "unknown unlock kind"; return(false); } string rpcAddress = cfg["rpc"]; if (string.IsNullOrWhiteSpace(rpcAddress)) { msg = "bitcoin.rpc is not set"; return(false); } string credential = cfg["credential"]; if (string.IsNullOrWhiteSpace(credential)) { msg = "bitcoin.credential is not set"; return(false); } string secret = cfg["secret"]; if (string.IsNullOrWhiteSpace(secret)) { msg = "bitcoin.secret is not set"; return(false); } // TODO disable confirmation config for release build string confirmationsCount = cfg["confirmationsCount"]; if (string.IsNullOrWhiteSpace(confirmationsCount)) { msg = "bitcoin.confirmationsCount is not set"; return(false); } var confirmationsExpected = 1; if (!int.TryParse(confirmationsCount, out confirmationsExpected)) { msg = "bitcoin.confirmationsCount is not an int"; return(false); } Network network = ((networkId == "1") ? Network.Main : Network.TestNet); var rpcClient = new RPCClient(credential, new Uri(rpcAddress), network); var transactionId = uint256.Parse(txFrom); var bitcoinPrivateKey = new BitcoinSecret(secret); if (bitcoinPrivateKey.Network != network) { msg = "Mismatching networks"; return(false); } var transactionResponse = rpcClient.GetRawTransaction(transactionId); Money transferAmount; if (!Money.TryParse(amountString, out transferAmount) || transferAmount <= 0) { msg = "Invalid amount"; return(false); } if (!int.TryParse(feeString, out int fee)) { msg = "bitcoin.fee is not an int"; return(false); } var receivedCoins = transactionResponse.Outputs.AsCoins(); OutPoint outPointToSpend = null; TxOut outTxToSpend = null; Money amount = null; foreach (var coin in receivedCoins) { if (coin.TxOut.ScriptPubKey == bitcoinPrivateKey.ScriptPubKey) { outPointToSpend = coin.Outpoint; outTxToSpend = coin.TxOut; amount = (Money)coin.Amount; if (amount.CompareTo(transferAmount + fee * 2) < 0) { msg = $"Invalid transaction - needed: {transferAmount}, has: {amount.ToString()}"; return(false); } break; } } if (outPointToSpend == null) { msg = "Invalid transaction - no outputs that the client can spend"; return(false); } var addressFrom = BitcoinAddress.Create(addressFromString, network); var addressTo = BitcoinAddress.Create(addressToString, network); var bitcoinTransactionBuilder = new TransactionBuilder(); var transaction = bitcoinTransactionBuilder .AddCoins(new Coin(outPointToSpend, outTxToSpend)) .AddKeys(bitcoinPrivateKey) .Send(addressTo.ScriptPubKey, transferAmount) .SendFees(new Money(fee, MoneyUnit.Satoshi)) .SetChange(addressFrom.ScriptPubKey) .BuildTransaction(true); if (!bitcoinTransactionBuilder.Verify(transaction)) { msg = "failed verify transaction"; return(false); } uint256 payTxId; try { payTxId = rpcClient.SendRawTransaction(transaction); } catch (RPCException e) { msg = $"failed to broadcast - error: {e.RPCCode}, reason: {e.RPCCodeMessage}"; return(false); } if (payTxId == null) { msg = "failed to broadcast - unknown error"; return(false); } while (true) //TODO: this may lock for a very long time or forever, fix --------------------------------------------------------------------------------------------------------------------------------------- { var transactionInfo = rpcClient.GetRawTransactionInfo(payTxId); if (transactionInfo != null && transactionInfo.BlockHash != null && transactionInfo.Confirmations >= confirmationsExpected) { break; } Thread.Sleep(1000); } command = new string[] { ccCommand, command[3], command[4] }; var tx = txBuilder.BuildTx(command, out msg); Debug.Assert(tx != null); Debug.Assert(msg == null); var content = new ByteArrayContent(tx); content.Headers.Add("Content-Type", "application/octet-stream"); msg = RpcHelper.CompleteBatch(httpClient, $"{creditcoinUrl}/batches", content); } msg = "Unknown command: " + command[0]; return(false); }
static void Main(string[] args) { try { string root = Directory.GetCurrentDirectory(); string pluginFolder = TxBuilder.GetPluginsFolder(root); if (pluginFolder == null) { Console.WriteLine("plugins subfolder not found"); return; } string progressId = ""; bool ignoreOldProgress = false; if (args.Length > 0 && args[0].StartsWith(progressParamPrefix)) { progressId = args[0].Substring(progressParamPrefix.Length); if (progressId[0] == '*') { ignoreOldProgress = true; progressId = progressId.Substring(1); } args = args.Skip(1).ToArray(); } string progress = Path.Combine(pluginFolder, $"progress{progressId}.txt"); if (ignoreOldProgress) { File.Delete(progress); } if (File.Exists(progress)) { Console.WriteLine("Found unfinished action, retrying..."); args = File.ReadAllText(progress).Split(); } else if (args.Length > 0) { File.WriteAllText(progress, string.Join(' ', args)); } if (args.Length < 1) { Console.WriteLine("Usage: ccclient [-progress:[*]progressId] [-config:configFileName] [-txid] command [parameters]"); Console.WriteLine("commands:"); Console.WriteLine("sighash"); Console.WriteLine("tip [numBlocksBelow]"); Console.WriteLine("list Settings"); Console.WriteLine("list Wallets"); Console.WriteLine("list Addresses"); Console.WriteLine("list Transfers"); Console.WriteLine("list AskOrders"); Console.WriteLine("list BidOrders"); Console.WriteLine("list Offers"); Console.WriteLine("list DealOrders"); Console.WriteLine("list RepaymentOrders"); Console.WriteLine("show Balance sighash|0"); Console.WriteLine("show Address sighash|0 blockchain address network"); Console.WriteLine("show MatchingOrders sighash|0"); Console.WriteLine("show CurrentOffers sighash|0"); Console.WriteLine("show CreditHistory sighash|0"); Console.WriteLine("show NewDeals sighash|0"); Console.WriteLine("show Transfer sighash|0 orderId"); Console.WriteLine("show CurrentLoans sighash|0"); Console.WriteLine("show NewRepaymentOrders sighash|0"); Console.WriteLine("show CurrentRepaymentOrders sighash|0"); Console.WriteLine("creditcoin SendFunds amount sighash "); Console.WriteLine("creditcoin RegisterAddress blockchain address network"); Console.WriteLine("creditcoin RegisterTransfer gain orderId txId"); Console.WriteLine("creditcoin AddAskOrder addressId amount interest maturity fee expiration"); Console.WriteLine("creditcoin AddBidOrder addressId amount interest maturity fee expiration"); Console.WriteLine("creditcoin AddOffer askOrderId bidOrderId expiration"); Console.WriteLine("creditcoin AddDealOrder offerId expiration"); Console.WriteLine("creditcoin CompleteDealOrder dealOrderId transferId"); Console.WriteLine("creditcoin LockDealOrder dealOrderId"); Console.WriteLine("creditcoin CloseDealOrder dealOrderId transferId"); Console.WriteLine("creditcoin Exempt dealOrderId transferId"); Console.WriteLine("creditcoin AddRepaymentOrder dealOrderId addressId amount expiration"); Console.WriteLine("creditcoin CompleteRepaymentOrder repaymentOrderId"); Console.WriteLine("creditcoin CloseRepaymentOrder repaymentOrderId transferId"); Console.WriteLine("creditcoin CollectCoins addressId amount txId"); Console.WriteLine("bitcoin RegisterTransfer gain orderId sourceTxId"); Console.WriteLine("ethereum RegisterTransfer gain orderId"); Console.WriteLine("ethereum CollectCoins amount"); return; } string configFile = null; if (args.Length > 0 && args[0].StartsWith(configParamPrefix)) { configFile = args[0].Substring(configParamPrefix.Length); args = args.Skip(1).ToArray(); if (!File.Exists(configFile)) { configFile = Path.Combine(pluginFolder, configFile); if (!File.Exists(configFile)) { Console.WriteLine("Cannot find the specified config file"); return; } } } bool txid = false; if (args.Length > 0 && args[0].Equals(txidParam)) { args = args.Skip(1).ToArray(); txid = true; } string action; string[] command; var builder = new ConfigurationBuilder() .AddJsonFile("appsettings.json", true, false) #if DEBUG .AddJsonFile("appsettings.dev.json", true, false) #endif ; if (configFile != null) { builder.AddJsonFile(configFile, true, false); } IConfiguration config = builder.Build(); string creditcoinRestApiURL = config["creditcoinRestApiURL"]; if (!string.IsNullOrWhiteSpace(creditcoinRestApiURL)) { creditcoinUrl = creditcoinRestApiURL; } Signer signer = getSigner(config); if (args.Length < 1) { Console.WriteLine("Command is not provided"); return; } action = args[0].ToLower(); command = args.Skip(1).ToArray(); bool inProgress = false; if (action.Equals("sighash")) { Console.WriteLine(TxBuilder.getSighash(signer)); } else if (action.Equals("tip")) { BigInteger headIdx = GetHeadIdx(); if (command.Length == 1) { BigInteger num; if (!BigInteger.TryParse(command[0], out num)) { throw new Exception("Invalid numerics"); } headIdx -= num; } Console.WriteLine(headIdx); } else if (action.Equals("list")) { if (command.Length > 2) { throw new Exception("1 or 2 parametersd expected"); } string id = null; if (command.Length == 2) { id = command[1]; } if (command[0].Equals("settings", StringComparison.OrdinalIgnoreCase)) { filter(RpcHelper.settingNamespace, (string objid, byte[] protobuf) => { if (id == null || id != null && id.Equals(objid)) { Setting setting = Setting.Parser.ParseFrom(protobuf); foreach (var entry in setting.Entries) { Console.WriteLine($"{entry.Key}: {entry.Value}"); } } }); } else if (command[0].Equals("wallets", StringComparison.OrdinalIgnoreCase)) { filter(RpcHelper.creditCoinNamespace + RpcHelper.walletPrefix, (string objid, byte[] protobuf) => { if (id == null || id != null && id.Equals(objid)) { Wallet wallet = Wallet.Parser.ParseFrom(protobuf); Console.WriteLine($"wallet({objid}) amount:{wallet.Amount}"); } }); } else if (command[0].Equals("addresses", StringComparison.OrdinalIgnoreCase)) { filter(RpcHelper.creditCoinNamespace + RpcHelper.addressPrefix, (string objid, byte[] protobuf) => { if (id == null || id != null && id.Equals(objid)) { Address address = Address.Parser.ParseFrom(protobuf); Console.WriteLine($"address({objid}) blockchain:{address.Blockchain} value:{address.Value} network:{address.Network} sighash:{address.Sighash}"); } }); } else if (command[0].Equals("transfers", StringComparison.OrdinalIgnoreCase)) { filter(RpcHelper.creditCoinNamespace + RpcHelper.transferPrefix, (string objid, byte[] protobuf) => { if (id == null || id != null && id.Equals(objid)) { Transfer transfer = Transfer.Parser.ParseFrom(protobuf); Console.WriteLine($"transfer({objid}) blockchain:{transfer.Blockchain} srcAddress:{transfer.SrcAddress} dstAddress:{transfer.DstAddress} order:{transfer.Order} amount:{transfer.Amount} tx:{transfer.Tx} block:{transfer.Block} processed:{transfer.Processed} sighash:{transfer.Sighash}"); } }); } else if (command[0].Equals("askOrders", StringComparison.OrdinalIgnoreCase)) { filter(RpcHelper.creditCoinNamespace + RpcHelper.askOrderPrefix, (string objid, byte[] protobuf) => { if (id == null || id != null && id.Equals(objid)) { AskOrder askOrder = AskOrder.Parser.ParseFrom(protobuf); Console.WriteLine($"askOrder({objid}) blockchain:{askOrder.Blockchain} address:{askOrder.Address} amount:{askOrder.Amount} interest:{askOrder.Interest} maturity:{askOrder.Maturity} fee:{askOrder.Fee} expiration:{askOrder.Expiration} block:{askOrder.Block} sighash:{askOrder.Sighash}"); } }); } else if (command[0].Equals("bidOrders", StringComparison.OrdinalIgnoreCase)) { filter(RpcHelper.creditCoinNamespace + RpcHelper.bidOrderPrefix, (string objid, byte[] protobuf) => { if (id == null || id != null && id.Equals(objid)) { BidOrder bidOrder = BidOrder.Parser.ParseFrom(protobuf); Console.WriteLine($"bidOrder({objid}) blockchain:{bidOrder.Blockchain} address:{bidOrder.Address} amount:{bidOrder.Amount} interest:{bidOrder.Interest} maturity:{bidOrder.Maturity} fee:{bidOrder.Fee} expiration:{bidOrder.Expiration} block:{bidOrder.Block} sighash:{bidOrder.Sighash}"); } }); } else if (command[0].Equals("offers", StringComparison.OrdinalIgnoreCase)) { filter(RpcHelper.creditCoinNamespace + RpcHelper.offerPrefix, (string objid, byte[] protobuf) => { if (id == null || id != null && id.Equals(objid)) { Offer offer = Offer.Parser.ParseFrom(protobuf); Console.WriteLine($"offer({objid}) blockchain:{offer.Blockchain} askOrder:{offer.AskOrder} bidOrder:{offer.BidOrder} expiration:{offer.Expiration} block:{offer.Block}"); } }); } else if (command[0].Equals("dealOrders", StringComparison.OrdinalIgnoreCase)) { filter(RpcHelper.creditCoinNamespace + RpcHelper.dealOrderPrefix, (string objid, byte[] protobuf) => { if (id == null || id != null && id.Equals(objid)) { DealOrder dealOrder = DealOrder.Parser.ParseFrom(protobuf); Console.WriteLine($"dealOrder({objid}) blockchain:{dealOrder.Blockchain} srcAddress:{dealOrder.SrcAddress} dstAddress:{dealOrder.DstAddress} amount:{dealOrder.Amount} interest:{dealOrder.Interest} maturity:{dealOrder.Maturity} fee:{dealOrder.Fee} expiration:{dealOrder.Expiration} block:{dealOrder.Block} loanTransfer:{(dealOrder.LoanTransfer.Equals(string.Empty) ? "*" : dealOrder.LoanTransfer)} repaymentTransfer:{(dealOrder.RepaymentTransfer.Equals(string.Empty) ? "*" : dealOrder.RepaymentTransfer)} lock:{(dealOrder.Lock.Equals(string.Empty) ? "*" : dealOrder.Lock)} sighash:{dealOrder.Sighash}"); } }); } else if (command[0].Equals("repaymentOrders", StringComparison.OrdinalIgnoreCase)) { filter(RpcHelper.creditCoinNamespace + RpcHelper.repaymentOrderPrefix, (string objid, byte[] protobuf) => { if (id == null || id != null && id.Equals(objid)) { RepaymentOrder repaymentOrder = RepaymentOrder.Parser.ParseFrom(protobuf); Console.WriteLine($"repaymentOrder({objid}) blockchain:{repaymentOrder.Blockchain} srcAddress:{repaymentOrder.SrcAddress} dstAddress:{repaymentOrder.DstAddress} amount:{repaymentOrder.Amount} expiration:{repaymentOrder.Expiration} block:{repaymentOrder.Block} deal:{repaymentOrder.Deal} previousOwner:{(repaymentOrder.PreviousOwner.Equals(string.Empty)? "*": repaymentOrder.PreviousOwner)} transfer:{(repaymentOrder.Transfer.Equals(string.Empty) ? "*" : repaymentOrder.Transfer)} sighash:{repaymentOrder.Sighash}"); } }); } } else if (action.Equals("show")) { bool success = true; BigInteger headIdx = GetHeadIdx(); if (command.Length <= 1) { throw new Exception("1 or more parametersd expected"); } string sighash; if (command[1].Equals("0")) { sighash = TxBuilder.getSighash(signer); } else { sighash = command[1]; } if (command[0].Equals("balance", StringComparison.OrdinalIgnoreCase)) { if (command.Length != 2) { throw new Exception("2 parametersd expected"); } string prefix = RpcHelper.creditCoinNamespace + RpcHelper.walletPrefix; string id = prefix + sighash; string amount = "0"; filter(prefix, (string objid, byte[] protobuf) => { Wallet wallet = Wallet.Parser.ParseFrom(protobuf); if (objid.Equals(id)) { amount = wallet.Amount; } }); Console.WriteLine($"{amount}"); } else if (command[0].Equals("address", StringComparison.OrdinalIgnoreCase)) { if (command.Length != 5) { throw new Exception("5 parametersd expected"); } var blockchain = command[2].ToLower(); var addr = command[3]; var network = command[4].ToLower(); filter(RpcHelper.creditCoinNamespace + RpcHelper.addressPrefix, (string objid, byte[] protobuf) => { Address address = Address.Parser.ParseFrom(protobuf); if (address.Sighash == sighash && address.Blockchain == blockchain && address.Value == addr && address.Network == network) { Console.WriteLine(objid); } }); } else if (command[0].Equals("matchingOrders", StringComparison.OrdinalIgnoreCase)) { if (command.Length != 2) { throw new Exception("2 parametersd expected"); } var askOrders = new Dictionary <string, AskOrder>(); filter(RpcHelper.creditCoinNamespace + RpcHelper.askOrderPrefix, (string objid, byte[] protobuf) => { AskOrder askOrder = AskOrder.Parser.ParseFrom(protobuf); BigInteger block; if (!BigInteger.TryParse(askOrder.Block, out block)) { throw new Exception("Invalid numerics"); } if (block + askOrder.Expiration > headIdx) { askOrders.Add(objid, askOrder); } }); var bidOrders = new Dictionary <string, BidOrder>(); filter(RpcHelper.creditCoinNamespace + RpcHelper.bidOrderPrefix, (string objid, byte[] protobuf) => { BidOrder bidOrder = BidOrder.Parser.ParseFrom(protobuf); BigInteger block; if (!BigInteger.TryParse(bidOrder.Block, out block)) { throw new Exception("Invalid numerics"); } if (block + bidOrder.Expiration > headIdx) { bidOrders.Add(objid, bidOrder); } }); match(sighash, askOrders, bidOrders); } else if (command[0].Equals("currentOffers", StringComparison.OrdinalIgnoreCase)) { if (command.Length != 2) { throw new Exception("2 parametersd expected"); } var bidOrders = new Dictionary <string, BidOrder>(); filter(RpcHelper.creditCoinNamespace + RpcHelper.bidOrderPrefix, (string objid, byte[] protobuf) => { BidOrder bidOrder = BidOrder.Parser.ParseFrom(protobuf); bidOrders.Add(objid, bidOrder); }); filter(RpcHelper.creditCoinNamespace + RpcHelper.offerPrefix, (string objid, byte[] protobuf) => { Offer offer = Offer.Parser.ParseFrom(protobuf); BidOrder bidOrder = bidOrders[offer.BidOrder]; if (bidOrder.Sighash == sighash) { BigInteger block; if (!BigInteger.TryParse(offer.Block, out block)) { throw new Exception("Invalid numerics"); } if (block + offer.Expiration > headIdx) { Console.WriteLine(objid); } } }); } else if (command[0].Equals("creditHistory", StringComparison.OrdinalIgnoreCase)) { if (command.Length != 2) { throw new Exception("2 parametersd expected"); } filterDeals(null, sighash, (string dealAddress, DealOrder dealOrder) => { var status = dealOrder.LoanTransfer.Equals(string.Empty) ? "NEW" : "COMPLETE"; if (!dealOrder.RepaymentTransfer.Equals(string.Empty)) { status = "CLOSED"; } Console.WriteLine($"status:{status}, amount:{dealOrder.Amount}, blockchain:{dealOrder.Blockchain}"); }); } else if (command[0].Equals("newDeals", StringComparison.OrdinalIgnoreCase)) { if (command.Length != 2) { throw new Exception("2 parametersd expected"); } filterDeals(sighash, null, (string dealAddress, DealOrder dealOrder) => { if (dealOrder.LoanTransfer.Equals(string.Empty)) { BigInteger block; if (!BigInteger.TryParse(dealOrder.Block, out block)) { throw new Exception("Invalid numerics"); } if (block + dealOrder.Expiration > headIdx) { Console.WriteLine(dealAddress); } } }); } else if (command[0].Equals("transfer", StringComparison.OrdinalIgnoreCase)) { if (command.Length != 3) { throw new Exception("3 parametersd expected"); } var orderId = command[2]; filter(RpcHelper.creditCoinNamespace + RpcHelper.transferPrefix, (string objid, byte[] protobuf) => { Transfer transfer = Transfer.Parser.ParseFrom(protobuf); if (transfer.Sighash == sighash && transfer.Order == orderId && !transfer.Processed) { Console.WriteLine(objid); } }); } else if (command[0].Equals("currentLoans", StringComparison.OrdinalIgnoreCase)) { if (command.Length != 2) { throw new Exception("2 parametersd expected"); } filterDeals(null, sighash, (string dealAddress, DealOrder dealOrder) => { if (!dealOrder.LoanTransfer.Equals(string.Empty) && dealOrder.RepaymentTransfer.Equals(string.Empty)) { Console.WriteLine(dealAddress); } }); } else if (command[0].Equals("newRepaymentOrders", StringComparison.OrdinalIgnoreCase)) { if (command.Length != 2) { throw new Exception("2 parametersd expected"); } var addresses = new Dictionary <string, Address>(); filter(RpcHelper.creditCoinNamespace + RpcHelper.addressPrefix, (string objid, byte[] protobuf) => { Address address = Address.Parser.ParseFrom(protobuf); addresses.Add(objid, address); }); var dealOrders = new Dictionary <string, DealOrder>(); filter(RpcHelper.creditCoinNamespace + RpcHelper.dealOrderPrefix, (string objid, byte[] protobuf) => { DealOrder dealOrder = DealOrder.Parser.ParseFrom(protobuf); dealOrders.Add(objid, dealOrder); }); filter(RpcHelper.creditCoinNamespace + RpcHelper.repaymentOrderPrefix, (string objid, byte[] protobuf) => { RepaymentOrder repaymentOrder = RepaymentOrder.Parser.ParseFrom(protobuf); DealOrder deal = dealOrders[repaymentOrder.Deal]; Address address = addresses[deal.SrcAddress]; if (repaymentOrder.Transfer.Equals(string.Empty) && repaymentOrder.PreviousOwner.Equals(string.Empty) && address.Sighash.Equals(sighash)) { BigInteger block; if (!BigInteger.TryParse(repaymentOrder.Block, out block)) { throw new Exception("Invalid numerics"); } if (block + repaymentOrder.Expiration > headIdx) { Console.WriteLine(objid); } } }); } else if (command[0].Equals("currentRepaymentOrders", StringComparison.OrdinalIgnoreCase)) { filter(RpcHelper.creditCoinNamespace + RpcHelper.repaymentOrderPrefix, (string objid, byte[] protobuf) => { RepaymentOrder repaymentOrder = RepaymentOrder.Parser.ParseFrom(protobuf); if (repaymentOrder.Transfer.Equals(string.Empty) && !repaymentOrder.PreviousOwner.Equals(string.Empty) && repaymentOrder.Sighash.Equals(sighash)) { Console.WriteLine(objid); } }); } else { Console.WriteLine("Invalid command " + command[0]); success = false; } if (success) { Console.WriteLine("Success"); } } else { var txBuilder = new TxBuilder(signer); if (action.Equals("creditcoin")) { string msg; var tx = txBuilder.BuildTx(command, out msg); if (tx == null) { Debug.Assert(msg != null); Console.WriteLine(msg); } else { Debug.Assert(msg == null); var content = new ByteArrayContent(tx); content.Headers.Add("Content-Type", "application/octet-stream"); Console.WriteLine(RpcHelper.CompleteBatch(httpClient, creditcoinUrl, "batches", content, txid)); } } else { var loader = new Loader <ICCClientPlugin>(); var msgs = new List <string>(); loader.Load(pluginFolder, msgs); foreach (var msg in msgs) { Console.WriteLine(msg); } ICCClientPlugin plugin = loader.Get(action); var pluginConfig = config.GetSection(action); if (plugin == null) { Console.WriteLine("Error: Unknown action " + action); } else { string msg; var settings = getSettings(); bool done = plugin.Run(txid, pluginConfig, httpClient, txBuilder, settings, progressId, pluginFolder, creditcoinUrl, command, out inProgress, out msg); if (done) { if (msg == null) { msg = "Success"; } Console.WriteLine(msg); } else { Console.WriteLine("Error: " + msg); } } } } if (!inProgress) { File.Delete(progress); } } catch (Exception x) { Console.WriteLine($"Error: unexpected failure - {x.Message}"); } }
public void New() { var txb = new TxBuilder(); Assert.NotNull(txb.Transaction, "TxBuilder.Transaction should be filled."); }