private void textBox_TextChanged(object sender, EventArgs e) { if (comboBox1.SelectedIndex < 0 || textBox1.TextLength == 0 || textBox2.TextLength == 0) { button1.Enabled = false; return; } try { Wallet.ToScriptHash(textBox1.Text); } catch (FormatException) { button1.Enabled = false; return; } Fixed8 amount; if (!Fixed8.TryParse(textBox2.Text, out amount)) { button1.Enabled = false; return; } if (amount.GetData() % (long)Math.Pow(10, 8 - (comboBox1.SelectedItem as RegisterTransaction).Precision) != 0) { button1.Enabled = false; return; } button1.Enabled = true; }
private string checkFields() { if (TxbAddressToAdd.Text.Length == 0) { return("STR_ERR_NOT_INPUT_ADDRESS"); } if (TxbAmount.Text.Length == 0) { return("STR_ERR_NOT_INPUT_AMOUNT"); } try { Pure.Wallets.Wallet.GetAddressVersion(TxbAddressToAdd.Text); } catch { return("STR_ERR_ADDRESS_FORMAT"); } Fixed8 amount; if (!Fixed8.TryParse(TxbAmount.Text, out amount)) { return("STR_ERR_AMOUNT_FORMAT"); } return("STR_SUCCESS"); }
private Transaction MakeTestTransaction(Random rnd) { Fixed8.TryParse((rnd.Next(1, 10000) * 0.00001).ToString(), out Fixed8 price); using (ScriptBuilder sb = new ScriptBuilder()) { sb.EmitSysCall("Zoro.NativeNEP5.Call", "Transfer", Genesis.BcpContractAddress, scriptHash, targetscripthash, new BigInteger(1)); InvocationTransaction tx = new InvocationTransaction { Nonce = Transaction.GetNonce(), Script = sb.ToArray(), GasPrice = price, GasLimit = Fixed8.FromDecimal(1000), Account = ZoroHelper.GetPublicKeyHash(keypair.PublicKey) }; tx.Attributes = new TransactionAttribute[0]; tx.Witnesses = new Witness[0]; byte[] data = ZoroHelper.GetHashData(tx); byte[] signdata = ZoroHelper.Sign(data, keypair.PrivateKey, keypair.PublicKey); ZoroHelper.AddWitness(tx, signdata, keypair.PublicKey); return(tx); } }
private void textBox_TextChanged(object sender, EventArgs e) { if (textBox1.TextLength == 0 || textBox2.TextLength == 0) { button1.Enabled = false; return; } try { Wallet.ToScriptHash(textBox1.Text); } catch (FormatException) { button1.Enabled = false; return; } Fixed8 amount; if (!Fixed8.TryParse(textBox2.Text, out amount)) { button1.Enabled = false; return; } button1.Enabled = true; }
public void TryParse_MinLongValueAsString_ParseReturnZero() { var minLongString = long.MinValue.ToString(); var tryParseResult = Fixed8.TryParse(minLongString, out var fixed8Result); tryParseResult.Should().BeFalse(); Asserting .That(fixed8Result) .IsZero(); // TODO #411 [AboimPinto]: Don't know if ZERO is the correct value when the TryParse fail. }
public void TryParse_MaxLongValueAsString_ParseReturnZero() { var maxLongString = long.MaxValue.ToString(); var tryParseResult = Fixed8.TryParse(maxLongString, out var fixed8Result); Assert.IsFalse(tryParseResult); Asserting .That(fixed8Result) .IsZero(); // TODO [AboimPinto]: Don't know if ZERO is the correct value when the TryParse fail. }
public void TryParse_InvalidLongValueAsString_ParseReturnFormatException() { const string invalidString = "xxx"; var tryParseResult = Fixed8.TryParse(invalidString, out var fixed8Result); tryParseResult.Should().BeFalse(); Asserting .That(fixed8Result) .IsZero(); // TODO #411 [AboimPinto]: Don't know if ZERO is the correct value when the TryParse fail. }
public void TryParse_ValidLongValueAsString_ParseIsOk() { const long longValue = 1; const int expectedFixed8LongValue = 100000000; var tryParseResult = Fixed8.TryParse(longValue.ToString(), out var fixed8Result); tryParseResult.Should().BeTrue(); Asserting .That(fixed8Result) .AsLongValue(expectedFixed8LongValue); }
private static Fixed8 GetGasConsumed(byte[] script) { RpcInvokeResult response = rpcClient.InvokeScript(script); if (Fixed8.TryParse(response.GasConsumed, out Fixed8 result)) { Fixed8 gas = result - Fixed8.FromDecimal(10); if (gas <= Fixed8.Zero) { return(Fixed8.Zero); } else { return(gas.Ceiling()); } } throw new Exception(); }
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { if (value is Fixed8) { return(value); } if (value is byte[] bytes && bytes.Length == FixedLength) { return(new Fixed8(BitConverter.ToInt64(bytes, 0))); } if (value is long l) { return(new Fixed8(l)); } if (value is string str && Fixed8.TryParse(str, out var res)) { return(res); } return(base.ConvertFrom(context, culture, value)); }
private void btnAdd_Click(object sender, RoutedEventArgs e) { string checkResult = checkFields(); if (checkResult != "STR_SUCCESS") { ShowErrorMessage(checkResult); return; } Fixed8 amount; Fixed8.TryParse(TxbAmount.Text, out amount); TxOutPutItem item = new TxOutPutItem(TxbAddressToAdd.Text, amount); item.RemoveTxOutPutItemEvent += RemoveTxOutputItemEvent; outPutItems.Add(item); this.stackOutPuts.Children.Add(item); calculateTotalAmount(); }
private void textBox_TextChanged(object sender, EventArgs e) { if (comboBox1.SelectedIndex < 0 || textBox1.TextLength == 0 || textBox2.TextLength == 0) { button1.Enabled = false; return; } try { Wallet.ToScriptHash(textBox1.Text); } catch (FormatException) { int i = textBox1.Text.IndexOf("@"); if (i <= 0 || i == textBox1.Text.Length - 1) { button1.Enabled = false; return; } } if (!Fixed8.TryParse(textBox2.Text, out Fixed8 amount)) { button1.Enabled = false; return; } if (amount == Fixed8.Zero) { button1.Enabled = false; return; } if (amount.GetData() % (long)Math.Pow(10, 8 - (comboBox1.SelectedItem as AssetDescriptor).Decimals) != 0) { button1.Enabled = false; return; } button1.Enabled = true; }
private bool OnSendCommand(string[] args) { if (Program.Wallet == null) { Console.WriteLine("You have to open the wallet first."); return(true); } if (args.Length < 4 || args.Length > 5) { Console.WriteLine("error"); return(true); } UInt256 assetId; switch (args[1].ToLower()) { case "ans": assetId = Blockchain.SystemShare.Hash; break; case "anc": assetId = Blockchain.SystemCoin.Hash; break; default: assetId = UInt256.Parse(args[1]); break; } UInt160 scriptHash = Wallet.ToScriptHash(args[2]); Fixed8 amount; if (!Fixed8.TryParse(args[3], out amount)) { Console.WriteLine("Incorrect Amount Format"); return(true); } if (amount.GetData() % (long)Math.Pow(10, 8 - Blockchain.Default.GetAssetState(assetId).Precision) != 0) { Console.WriteLine("Incorrect Amount Precision"); return(true); } Fixed8 fee = args.Length >= 5 ? Fixed8.Parse(args[4]) : Fixed8.Zero; ContractTransaction tx = Program.Wallet.MakeTransaction(new ContractTransaction { Outputs = new[] { new TransactionOutput { AssetId = assetId, Value = amount, ScriptHash = scriptHash } } }, fee: fee); if (tx == null) { Console.WriteLine("Insufficient funds"); return(true); } using (SecureString password = ReadSecureString("password")) { if (password.Length == 0) { Console.WriteLine("cancelled"); return(true); } if (!Program.Wallet.VerifyPassword(password)) { Console.WriteLine("Incorrect password"); return(true); } } SignatureContext context = new SignatureContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Scripts = context.GetScripts(); Program.Wallet.SaveTransaction(tx); LocalNode.Relay(tx); Console.WriteLine($"TXID: {tx.Hash}"); } else { Console.WriteLine("SignatureContext:"); Console.WriteLine(context.ToString()); } return(true); }
public void DoWork() { #region Checking Fields Global.AssetDescriptor asset = Asset as Global.AssetDescriptor; string fromAddress = FromAddr; string toAddress = ToAddr; string strAmount = Amount; string strFee = Fee; byte toAddrVersion; byte fromAddrVersion; if (asset == null) { throw new InvalidOperationException("Anchor is not correct"); } if (!Fixed8.TryParse(strAmount, out Fixed8 amount)) { throw new InvalidOperationException("Anchor is not correct"); } if (amount == Fixed8.Zero) { throw new InvalidOperationException("Anchor is not correct"); } if (amount.GetData() % (long)Math.Pow(10, 8 - (Asset as Global.AssetDescriptor).Precision) != 0) { throw new InvalidOperationException("Anchor is not correct"); } if (!Fixed8.TryParse(strFee, out Fixed8 fee)) { throw new InvalidOperationException("Anchor is not correct"); } if (fee < Fixed8.Zero) { throw new InvalidOperationException("Anchor is not correct"); } try { fromAddrVersion = Wallet.GetAddressVersion(fromAddress); toAddrVersion = Wallet.GetAddressVersion(toAddress); } catch { throw new InvalidOperationException("Anchor is not correct"); } Transaction tx; #endregion #region T -> T if (toAddrVersion == Wallet.AddressVersion && fromAddrVersion == Wallet.AddressVersion) // T -> T { List <TransactionAttribute> attributes = new List <TransactionAttribute>(); tx = new ContractTransaction(); //if (!string.IsNullOrEmpty(remark)) // attributes.Add(new TransactionAttribute // { // Usage = TransactionAttributeUsage.Remark, // Data = Encoding.UTF8.GetBytes(remark) // }); tx.Attributes = attributes.ToArray(); TransactionOutput outPut = new TransactionOutput(); outPut.ScriptHash = Wallet.ToScriptHash(toAddress); outPut.Value = amount; outPut.AssetId = (UInt256)asset.AssetId; outPut.Fee = fee; tx.Outputs = new TransactionOutput[1]; tx.Outputs[0] = outPut; if (tx is ContractTransaction ctx) { tx = Constant.CurrentWallet.MakeTransactionFrom(ctx, fromAddress); if (tx == null) { throw new InvalidOperationException("Anchor is not correct"); } } Helper.SignAndShowInformation(tx); } #endregion #region T -> A else if (fromAddrVersion == Wallet.AddressVersion && toAddrVersion == Wallet.AnonymouseAddressVersion) // T -> A { UInt256 joinSplitPubKey_; byte[] joinSplitPrivKey_; List <TransactionAttribute> attributes = new List <TransactionAttribute>(); tx = new AnonymousContractTransaction(); tx.Attributes = attributes.ToArray(); Sodium.KeyPair keyPair; keyPair = Sodium.PublicKeyAuth.GenerateKeyPair(); joinSplitPubKey_ = new UInt256(keyPair.PublicKey); joinSplitPrivKey_ = keyPair.PrivateKey; ((AnonymousContractTransaction)tx).joinSplitPubKey = joinSplitPubKey_; AsyncJoinSplitInfo info = new AsyncJoinSplitInfo(); info.vpub_old = new Fixed8(0); info.vpub_new = new Fixed8(0); JSOutput jsOut = new JSOutput(Wallet.ToPaymentAddress(toAddress), amount, fee, (UInt256)asset.AssetId); info.vjsout.Add(jsOut); info.vpub_old += amount; if (tx is AnonymousContractTransaction ctx) { tx = Constant.CurrentWallet.MakeTandATransaction(ctx, fromAddress, info); if (tx is AnonymousContractTransaction ctx_) { IntPtr w = SnarkDllApi.Witnesses_Create(); IntPtr ptrRoot = SnarkDllApi.GetCMRoot(Blockchain.Default.GetCmMerkleTree()); byte[] byRoot = new byte[32]; System.Runtime.InteropServices.Marshal.Copy(ptrRoot, byRoot, 0, 32); UInt256 anchor = new UInt256(byRoot); tx = Constant.CurrentWallet.Perform_JoinSplit(ctx_, info, joinSplitPubKey_, joinSplitPrivKey_, (UInt256)asset.AssetId, w, anchor); ctx_.joinSplitSig = Sodium.PublicKeyAuth.SignDetached(ctx.JsHash.ToArray(), joinSplitPrivKey_); if (!Sodium.PublicKeyAuth.VerifyDetached(ctx_.joinSplitSig, ctx.JsHash.ToArray(), joinSplitPubKey_.ToArray())) { throw new InvalidOperationException("Anchor is not correct"); } } else { throw new InvalidOperationException("Anchor is not correct"); } } else { throw new InvalidOperationException("Anchor is not correct"); } Helper.SignAndShowInformation(tx); } #endregion #region A -> T else if (fromAddrVersion == Wallet.AnonymouseAddressVersion && toAddrVersion == Wallet.AddressVersion) // A -> T { UInt256 joinSplitPubKey_; byte[] joinSplitPrivKey_; List <TransactionAttribute> attributes = new List <TransactionAttribute>(); tx = new AnonymousContractTransaction(); Fixed8 vpubNewTarget = Fixed8.Zero; Fixed8 totalAmount = amount; tx.Attributes = attributes.ToArray(); Sodium.KeyPair keyPair; keyPair = Sodium.PublicKeyAuth.GenerateKeyPair(); joinSplitPubKey_ = new UInt256(keyPair.PublicKey); joinSplitPrivKey_ = keyPair.PrivateKey; ((AnonymousContractTransaction)tx).joinSplitPubKey = joinSplitPubKey_; // Do process the transparent outputs. TransactionOutput outPut = new TransactionOutput(); outPut.ScriptHash = Wallet.ToScriptHash(toAddress); outPut.Value = amount; outPut.AssetId = (UInt256)asset.AssetId; tx.Outputs = new TransactionOutput[1]; tx.Outputs[0] = outPut; tx.Scripts = new Witness[0]; vpubNewTarget = amount; AsyncJoinSplitInfo info = new AsyncJoinSplitInfo(); info.vpub_old = Fixed8.Zero; info.vpub_new = Fixed8.Zero; Fixed8 jsInputValue = Fixed8.Zero; IntPtr ptrRoot = SnarkDllApi.GetCMRoot(Blockchain.Default.GetCmMerkleTree()); byte[] byRoot = new byte[32]; System.Runtime.InteropServices.Marshal.Copy(ptrRoot, byRoot, 0, 32); UInt256 jsAnchor = new UInt256(byRoot); if (tx is AnonymousContractTransaction ctx) { tx = Constant.CurrentWallet.MakeAandTTransaction(ctx, fromAddress, info); #region Split token types /* ****************************** Split the info into main token and fee token ********************************** */ AsyncJoinSplitInfo mainTokenInfo = new AsyncJoinSplitInfo(); AsyncJoinSplitInfo subTokenInfo = new AsyncJoinSplitInfo(); Fixed8 main_total_output_amount = Fixed8.Zero; Fixed8 sub_total_output_amount = Fixed8.Zero; for (int i = 0; i < info.vjsin.Count; i++) { if (info.vjsin[i].AssetID == Blockchain.UtilityToken.Hash) { subTokenInfo.vjsin.Add(info.vjsin[i]); subTokenInfo.notes.Add(info.vjsin[i].note); } else { mainTokenInfo.vjsin.Add(info.vjsin[i]); mainTokenInfo.notes.Add(info.vjsin[i].note); } } for (int i = 0; i < info.vjsout.Count; i++) { if (info.vjsout[i].AssetID == Blockchain.UtilityToken.Hash) { subTokenInfo.vjsout.Add(info.vjsout[i]); sub_total_output_amount += info.vjsout[i].value; } else { mainTokenInfo.vjsout.Add(info.vjsout[i]); main_total_output_amount += info.vjsout[i].value; } } /* ****************************** End ********************************** */ #endregion IntPtr vectorWitness = SnarkDllApi.Witnesses_Create(); int jsIndex = 0; Fixed8 current_inputed_amount = Fixed8.Zero; Fixed8 rest_amount = totalAmount; #region Do Process the Main token part for (int i = 0; i < mainTokenInfo.vjsin.Count; i++) { IntPtr witness = SnarkDllApi.CmWitness_Create(); SnarkDllApi.SetCMWitnessFromBinary(witness, mainTokenInfo.vjsin[i].witness, mainTokenInfo.vjsin[i].witness.Length); SnarkDllApi.Witnesses_Add(vectorWitness, witness); IntPtr ptrWitness = SnarkDllApi.GetCMRootFromWitness(witness); byte[] byWRoot = new byte[32]; System.Runtime.InteropServices.Marshal.Copy(ptrWitness, byWRoot, 0, 32); UInt256 wAnchor = new UInt256(byWRoot); if (jsAnchor != wAnchor) { throw new InvalidOperationException("Anchor is not correct"); } current_inputed_amount += mainTokenInfo.vjsin[i].note.value; jsIndex++; if (jsIndex == 2 && i != mainTokenInfo.vjsin.Count - 1) { AsyncJoinSplitInfo jsInfo = new AsyncJoinSplitInfo(); jsInfo.vjsin.Add(mainTokenInfo.vjsin[i - 1]); jsInfo.vjsin.Add(mainTokenInfo.vjsin[i]); jsInfo.notes.Add(mainTokenInfo.notes[i - 1]); jsInfo.notes.Add(mainTokenInfo.notes[i]); var vInputsSum = jsInfo.vjsin[0].note.value + jsInfo.vjsin[1].note.value; for (int oti = 0; oti < mainTokenInfo.vjsout.Count; oti++) { if (mainTokenInfo.vjsout[oti].value >= vInputsSum) { JSOutput jsOut1 = new JSOutput(mainTokenInfo.vjsout[oti].addr, vInputsSum, mainTokenInfo.vjsout[oti].AssetID); jsInfo.vjsout.Add(jsOut1); mainTokenInfo.vjsout[oti].value -= vInputsSum; vInputsSum = Fixed8.Zero; break; } if (mainTokenInfo.vjsout[oti].value < vInputsSum) { JSOutput jsOut1 = new JSOutput(mainTokenInfo.vjsout[oti].addr, mainTokenInfo.vjsout[oti].value, mainTokenInfo.vjsout[oti].AssetID); jsInfo.vjsout.Add(jsOut1); vInputsSum = vInputsSum - mainTokenInfo.vjsout[oti].value; mainTokenInfo.vjsout[oti].value = Fixed8.Zero; } } if (vInputsSum >= Fixed8.Zero) { jsInfo.vpub_new = vInputsSum; } tx = Constant.CurrentWallet.Perform_JoinSplit(ctx, jsInfo, joinSplitPubKey_, joinSplitPrivKey_, (UInt256)jsInfo.vjsin[0].AssetID, vectorWitness, jsAnchor); jsIndex = 0; SnarkDllApi.Witnesses_Clear(vectorWitness); } if (i == mainTokenInfo.vjsin.Count - 1) { AsyncJoinSplitInfo jsInfo = new AsyncJoinSplitInfo(); Fixed8 jsInputedAmount = Fixed8.Zero; for (int ji = jsIndex - 1; ji > -1; ji--) { jsInfo.vjsin.Add(mainTokenInfo.vjsin[i - ji]); jsInfo.notes.Add(mainTokenInfo.notes[i - ji]); jsInputedAmount += mainTokenInfo.notes[i - ji].value; rest_amount -= mainTokenInfo.notes[i - ji].value; } for (int oti = 0; oti < mainTokenInfo.vjsout.Count; oti++) { if (mainTokenInfo.vjsout[oti].value >= jsInputedAmount) { JSOutput jsOut1 = new JSOutput(mainTokenInfo.vjsout[oti].addr, jsInputedAmount, mainTokenInfo.vjsout[oti].AssetID); jsInfo.vjsout.Add(jsOut1); mainTokenInfo.vjsout[oti].value -= jsInputedAmount; jsInputedAmount = Fixed8.Zero; break; } if (mainTokenInfo.vjsout[oti].value < jsInputedAmount) { JSOutput jsOut1 = new JSOutput(mainTokenInfo.vjsout[oti].addr, mainTokenInfo.vjsout[oti].value, mainTokenInfo.vjsout[oti].AssetID); jsInfo.vjsout.Add(jsOut1); jsInputedAmount = jsInputedAmount - mainTokenInfo.vjsout[oti].value; mainTokenInfo.vjsout[oti].value = Fixed8.Zero; } } if (jsInputedAmount != Fixed8.Zero) { jsInfo.vpub_new = jsInputedAmount; } try { tx = Constant.CurrentWallet.Perform_JoinSplit(ctx, jsInfo, joinSplitPubKey_, joinSplitPrivKey_, (UInt256)jsInfo.vjsin[0].AssetID, vectorWitness, jsAnchor); } catch (Exception ex) { string strException = ex.Message; throw new InvalidOperationException("JoinSplit Errors"); } if (tx.Inputs == null) { tx.Inputs = new CoinReference[0]; } jsIndex = 0; SnarkDllApi.Witnesses_Clear(vectorWitness); } } #endregion #region Do Process the Fee token part, And when sending the QRG token, then there is no Main token part. for (int i = 0; i < subTokenInfo.vjsin.Count; i++) { IntPtr witness = SnarkDllApi.CmWitness_Create(); SnarkDllApi.SetCMWitnessFromBinary(witness, subTokenInfo.vjsin[i].witness, subTokenInfo.vjsin[i].witness.Length); SnarkDllApi.Witnesses_Add(vectorWitness, witness); IntPtr ptrWitness = SnarkDllApi.GetCMRootFromWitness(witness); byte[] byWRoot = new byte[32]; System.Runtime.InteropServices.Marshal.Copy(ptrWitness, byWRoot, 0, 32); UInt256 wAnchor = new UInt256(byWRoot); if (jsAnchor != wAnchor) { throw new InvalidOperationException("Anchor is not correct"); } current_inputed_amount += subTokenInfo.vjsin[i].note.value; jsIndex++; if (jsIndex == 2 && i != subTokenInfo.vjsin.Count - 1) { AsyncJoinSplitInfo jsInfo = new AsyncJoinSplitInfo(); jsInfo.vjsin.Add(subTokenInfo.vjsin[i - 1]); jsInfo.vjsin.Add(subTokenInfo.vjsin[i]); jsInfo.notes.Add(subTokenInfo.notes[i - 1]); jsInfo.notes.Add(subTokenInfo.notes[i]); var vInputsSum = jsInfo.vjsin[0].note.value + jsInfo.vjsin[1].note.value; for (int oti = 0; oti < subTokenInfo.vjsout.Count; oti++) { if (subTokenInfo.vjsout[oti].value >= vInputsSum) { JSOutput jsOut1 = new JSOutput(subTokenInfo.vjsout[oti].addr, vInputsSum, subTokenInfo.vjsout[oti].AssetID); jsInfo.vjsout.Add(jsOut1); subTokenInfo.vjsout[oti].value -= vInputsSum; vInputsSum = Fixed8.Zero; break; } if (subTokenInfo.vjsout[oti].value < vInputsSum) { JSOutput jsOut1 = new JSOutput(subTokenInfo.vjsout[oti].addr, subTokenInfo.vjsout[oti].value, subTokenInfo.vjsout[oti].AssetID); jsInfo.vjsout.Add(jsOut1); vInputsSum = vInputsSum - subTokenInfo.vjsout[oti].value; subTokenInfo.vjsout[oti].value = Fixed8.Zero; } } if (vInputsSum >= Fixed8.Zero) { jsInfo.vpub_new = vInputsSum; } tx = Constant.CurrentWallet.Perform_JoinSplit(ctx, jsInfo, joinSplitPubKey_, joinSplitPrivKey_, (UInt256)jsInfo.vjsin[0].AssetID, vectorWitness, jsAnchor); jsIndex = 0; SnarkDllApi.Witnesses_Clear(vectorWitness); } if (i == subTokenInfo.vjsin.Count - 1) { AsyncJoinSplitInfo jsInfo = new AsyncJoinSplitInfo(); Fixed8 jsInputedAmount = Fixed8.Zero; for (int ji = jsIndex - 1; ji > -1; ji--) { jsInfo.vjsin.Add(subTokenInfo.vjsin[i - ji]); jsInfo.notes.Add(subTokenInfo.notes[i - ji]); jsInputedAmount += subTokenInfo.notes[i - ji].value; rest_amount -= subTokenInfo.notes[i - ji].value; } for (int oti = 0; oti < subTokenInfo.vjsout.Count; oti++) { if (subTokenInfo.vjsout[oti].value >= jsInputedAmount) { JSOutput jsOut1 = new JSOutput(subTokenInfo.vjsout[oti].addr, jsInputedAmount, subTokenInfo.vjsout[oti].AssetID); jsInfo.vjsout.Add(jsOut1); subTokenInfo.vjsout[oti].value -= jsInputedAmount; jsInputedAmount = Fixed8.Zero; break; } if (subTokenInfo.vjsout[oti].value < jsInputedAmount) { JSOutput jsOut1 = new JSOutput(subTokenInfo.vjsout[oti].addr, subTokenInfo.vjsout[oti].value, subTokenInfo.vjsout[oti].AssetID); jsInfo.vjsout.Add(jsOut1); jsInputedAmount = jsInputedAmount - subTokenInfo.vjsout[oti].value; subTokenInfo.vjsout[oti].value = Fixed8.Zero; } } if (jsInputedAmount != Fixed8.Zero) { jsInfo.vpub_new = jsInputedAmount; } try { tx = Constant.CurrentWallet.Perform_JoinSplit(ctx, jsInfo, joinSplitPubKey_, joinSplitPrivKey_, (UInt256)jsInfo.vjsin[0].AssetID, vectorWitness, jsAnchor); } catch (Exception ex) { string strException = ex.Message; throw new InvalidOperationException("JoinSplit Errors"); } if (tx.Inputs == null) { tx.Inputs = new CoinReference[0]; } jsIndex = 0; SnarkDllApi.Witnesses_Clear(vectorWitness); } } #endregion ctx.joinSplitSig = Sodium.PublicKeyAuth.SignDetached(ctx.JsHash.ToArray(), joinSplitPrivKey_); if (!Sodium.PublicKeyAuth.VerifyDetached(ctx.joinSplitSig, ctx.JsHash.ToArray(), joinSplitPubKey_.ToArray())) { throw new InvalidOperationException("Anchor is not correct"); } } else { throw new InvalidOperationException("Anchor is not correct"); } Helper.SignAndShowInformation(tx); } #endregion #region A -> A else if (fromAddrVersion == Wallet.AnonymouseAddressVersion && toAddrVersion == Wallet.AnonymouseAddressVersion) // A -> A { UInt256 joinSplitPubKey_; byte[] joinSplitPrivKey_; List <TransactionAttribute> attributes = new List <TransactionAttribute>(); tx = new AnonymousContractTransaction(); Fixed8 totalAmount = amount; tx.Scripts = new Witness[0]; tx.Attributes = attributes.ToArray(); Sodium.KeyPair keyPair; keyPair = Sodium.PublicKeyAuth.GenerateKeyPair(); joinSplitPubKey_ = new UInt256(keyPair.PublicKey); joinSplitPrivKey_ = keyPair.PrivateKey; ((AnonymousContractTransaction)tx).joinSplitPubKey = joinSplitPubKey_; AsyncJoinSplitInfo info = new AsyncJoinSplitInfo(); info.vpub_old = Fixed8.Zero; info.vpub_new = Fixed8.Zero; JSOutput jsOut = new JSOutput(Wallet.ToPaymentAddress(toAddress), amount, (UInt256)asset.AssetId); info.vjsout.Add(jsOut); Fixed8 jsInputValue = Fixed8.Zero; IntPtr ptrRoot = SnarkDllApi.GetCMRoot(Blockchain.Default.GetCmMerkleTree()); byte[] byRoot = new byte[32]; System.Runtime.InteropServices.Marshal.Copy(ptrRoot, byRoot, 0, 32); UInt256 jsAnchor = new UInt256(byRoot); if (tx is AnonymousContractTransaction ctx) { tx = Constant.CurrentWallet.MakeAandATransaction(ctx, fromAddress, info); #region Split token type /* ****************************** Split the info into main token and fee token ********************************** */ AsyncJoinSplitInfo mainTokenInfo = new AsyncJoinSplitInfo(); AsyncJoinSplitInfo subTokenInfo = new AsyncJoinSplitInfo(); Fixed8 main_total_output_amount = Fixed8.Zero; Fixed8 sub_total_output_amount = Fixed8.Zero; for (int i = 0; i < info.vjsin.Count; i++) { if (info.vjsin[i].AssetID == Blockchain.UtilityToken.Hash) { subTokenInfo.vjsin.Add(info.vjsin[i]); subTokenInfo.notes.Add(info.vjsin[i].note); } else { mainTokenInfo.vjsin.Add(info.vjsin[i]); mainTokenInfo.notes.Add(info.vjsin[i].note); } } for (int i = 0; i < info.vjsout.Count; i++) { if (info.vjsout[i].AssetID == Blockchain.UtilityToken.Hash) { subTokenInfo.vjsout.Add(info.vjsout[i]); sub_total_output_amount += info.vjsout[i].value; } else { mainTokenInfo.vjsout.Add(info.vjsout[i]); main_total_output_amount += info.vjsout[i].value; } } /* ****************************** End ********************************** */ #endregion IntPtr vectorWitness = SnarkDllApi.Witnesses_Create(); int jsIndex = 0; Fixed8 current_inputed_amount = Fixed8.Zero; Fixed8 rest_amount = totalAmount; #region Do Process the Main token part for (int i = 0; i < mainTokenInfo.vjsin.Count; i++) { IntPtr witness = SnarkDllApi.CmWitness_Create(); SnarkDllApi.SetCMWitnessFromBinary(witness, mainTokenInfo.vjsin[i].witness, mainTokenInfo.vjsin[i].witness.Length); SnarkDllApi.Witnesses_Add(vectorWitness, witness); IntPtr ptrWitness = SnarkDllApi.GetCMRootFromWitness(witness); byte[] byWRoot = new byte[32]; System.Runtime.InteropServices.Marshal.Copy(ptrWitness, byWRoot, 0, 32); UInt256 wAnchor = new UInt256(byWRoot); if (jsAnchor != wAnchor) { throw new InvalidOperationException("Anchor is not correct"); } current_inputed_amount += mainTokenInfo.vjsin[i].note.value; jsIndex++; if (jsIndex == 2 && i != mainTokenInfo.vjsin.Count - 1) { AsyncJoinSplitInfo jsInfo = new AsyncJoinSplitInfo(); jsInfo.vjsin.Add(mainTokenInfo.vjsin[i - 1]); jsInfo.vjsin.Add(mainTokenInfo.vjsin[i]); jsInfo.notes.Add(mainTokenInfo.notes[i - 1]); jsInfo.notes.Add(mainTokenInfo.notes[i]); var vInputsSum = jsInfo.vjsin[0].note.value + jsInfo.vjsin[1].note.value; for (int oti = 0; oti < mainTokenInfo.vjsout.Count; oti++) { if (mainTokenInfo.vjsout[oti].value >= vInputsSum) { JSOutput jsOut1 = new JSOutput(mainTokenInfo.vjsout[oti].addr, vInputsSum, mainTokenInfo.vjsout[oti].AssetID); jsInfo.vjsout.Add(jsOut1); mainTokenInfo.vjsout[oti].value -= vInputsSum; vInputsSum = Fixed8.Zero; break; } if (mainTokenInfo.vjsout[oti].value < vInputsSum) { JSOutput jsOut1 = new JSOutput(mainTokenInfo.vjsout[oti].addr, mainTokenInfo.vjsout[oti].value, mainTokenInfo.vjsout[oti].AssetID); jsInfo.vjsout.Add(jsOut1); vInputsSum = vInputsSum - mainTokenInfo.vjsout[oti].value; mainTokenInfo.vjsout[oti].value = Fixed8.Zero; } } tx = Constant.CurrentWallet.Perform_JoinSplit(ctx, jsInfo, joinSplitPubKey_, joinSplitPrivKey_, (UInt256)jsInfo.vjsin[0].AssetID, vectorWitness, jsAnchor); jsIndex = 0; SnarkDllApi.Witnesses_Clear(vectorWitness); } if (i == mainTokenInfo.vjsin.Count - 1) { AsyncJoinSplitInfo jsInfo = new AsyncJoinSplitInfo(); Fixed8 jsInputedAmount = Fixed8.Zero; for (int ji = jsIndex - 1; ji > -1; ji--) { jsInfo.vjsin.Add(mainTokenInfo.vjsin[i - ji]); jsInfo.notes.Add(mainTokenInfo.notes[i - ji]); jsInputedAmount += mainTokenInfo.notes[i - ji].value; rest_amount -= mainTokenInfo.notes[i - ji].value; } for (int oti = 0; oti < mainTokenInfo.vjsout.Count; oti++) { if (mainTokenInfo.vjsout[oti].value >= jsInputedAmount) { JSOutput jsOut1 = new JSOutput(mainTokenInfo.vjsout[oti].addr, jsInputedAmount, mainTokenInfo.vjsout[oti].AssetID); jsInfo.vjsout.Add(jsOut1); mainTokenInfo.vjsout[oti].value -= jsInputedAmount; jsInputedAmount = Fixed8.Zero; break; } if (mainTokenInfo.vjsout[oti].value < jsInputedAmount) { JSOutput jsOut1 = new JSOutput(mainTokenInfo.vjsout[oti].addr, mainTokenInfo.vjsout[oti].value, mainTokenInfo.vjsout[oti].AssetID); jsInfo.vjsout.Add(jsOut1); jsInputedAmount = jsInputedAmount - mainTokenInfo.vjsout[oti].value; mainTokenInfo.vjsout[oti].value = Fixed8.Zero; } } if (jsInputedAmount != Fixed8.Zero) { jsInfo.vpub_new = jsInputedAmount; } try { tx = Constant.CurrentWallet.Perform_JoinSplit(ctx, jsInfo, joinSplitPubKey_, joinSplitPrivKey_, (UInt256)jsInfo.vjsin[0].AssetID, vectorWitness, jsAnchor); } catch (Exception ex) { string strException = ex.Message; throw new InvalidOperationException("JoinSplit Errors"); } if (tx.Inputs == null) { tx.Inputs = new CoinReference[0]; } jsIndex = 0; SnarkDllApi.Witnesses_Clear(vectorWitness); } } #endregion #region Do Process the Fee token part, And when sending the QRG token, then there is no Main token part. for (int i = 0; i < subTokenInfo.vjsin.Count; i++) { IntPtr witness = SnarkDllApi.CmWitness_Create(); SnarkDllApi.SetCMWitnessFromBinary(witness, subTokenInfo.vjsin[i].witness, subTokenInfo.vjsin[i].witness.Length); SnarkDllApi.Witnesses_Add(vectorWitness, witness); IntPtr ptrWitness = SnarkDllApi.GetCMRootFromWitness(witness); byte[] byWRoot = new byte[32]; System.Runtime.InteropServices.Marshal.Copy(ptrWitness, byWRoot, 0, 32); UInt256 wAnchor = new UInt256(byWRoot); if (jsAnchor != wAnchor) { throw new InvalidOperationException("Anchor is not correct"); } current_inputed_amount += subTokenInfo.vjsin[i].note.value; jsIndex++; if (jsIndex == 2 && i != subTokenInfo.vjsin.Count - 1) { AsyncJoinSplitInfo jsInfo = new AsyncJoinSplitInfo(); jsInfo.vjsin.Add(subTokenInfo.vjsin[i - 1]); jsInfo.vjsin.Add(subTokenInfo.vjsin[i]); jsInfo.notes.Add(subTokenInfo.notes[i - 1]); jsInfo.notes.Add(subTokenInfo.notes[i]); var vInputsSum = jsInfo.vjsin[0].note.value + jsInfo.vjsin[1].note.value; for (int oti = 0; oti < subTokenInfo.vjsout.Count; oti++) { if (subTokenInfo.vjsout[oti].value >= vInputsSum) { JSOutput jsOut1 = new JSOutput(subTokenInfo.vjsout[oti].addr, vInputsSum, subTokenInfo.vjsout[oti].AssetID); jsInfo.vjsout.Add(jsOut1); subTokenInfo.vjsout[oti].value -= vInputsSum; vInputsSum = Fixed8.Zero; break; } if (subTokenInfo.vjsout[oti].value < vInputsSum) { JSOutput jsOut1 = new JSOutput(subTokenInfo.vjsout[oti].addr, subTokenInfo.vjsout[oti].value, subTokenInfo.vjsout[oti].AssetID); jsInfo.vjsout.Add(jsOut1); vInputsSum = vInputsSum - subTokenInfo.vjsout[oti].value; subTokenInfo.vjsout[oti].value = Fixed8.Zero; } } tx = Constant.CurrentWallet.Perform_JoinSplit(ctx, jsInfo, joinSplitPubKey_, joinSplitPrivKey_, (UInt256)jsInfo.vjsin[0].AssetID, vectorWitness, jsAnchor); jsIndex = 0; SnarkDllApi.Witnesses_Clear(vectorWitness); } if (i == subTokenInfo.vjsin.Count - 1) { AsyncJoinSplitInfo jsInfo = new AsyncJoinSplitInfo(); Fixed8 jsInputedAmount = Fixed8.Zero; for (int ji = jsIndex - 1; ji > -1; ji--) { jsInfo.vjsin.Add(subTokenInfo.vjsin[i - ji]); jsInfo.notes.Add(subTokenInfo.notes[i - ji]); jsInputedAmount += subTokenInfo.notes[i - ji].value; rest_amount -= subTokenInfo.notes[i - ji].value; } for (int oti = 0; oti < subTokenInfo.vjsout.Count; oti++) { if (subTokenInfo.vjsout[oti].value >= jsInputedAmount) { JSOutput jsOut1 = new JSOutput(subTokenInfo.vjsout[oti].addr, jsInputedAmount, subTokenInfo.vjsout[oti].AssetID); jsInfo.vjsout.Add(jsOut1); subTokenInfo.vjsout[oti].value -= jsInputedAmount; jsInputedAmount = Fixed8.Zero; break; } if (subTokenInfo.vjsout[oti].value < jsInputedAmount) { JSOutput jsOut1 = new JSOutput(subTokenInfo.vjsout[oti].addr, subTokenInfo.vjsout[oti].value, subTokenInfo.vjsout[oti].AssetID); jsInfo.vjsout.Add(jsOut1); jsInputedAmount = jsInputedAmount - subTokenInfo.vjsout[oti].value; subTokenInfo.vjsout[oti].value = Fixed8.Zero; } } if (jsInputedAmount != Fixed8.Zero) { jsInfo.vpub_new = jsInputedAmount; } try { tx = Constant.CurrentWallet.Perform_JoinSplit(ctx, jsInfo, joinSplitPubKey_, joinSplitPrivKey_, (UInt256)jsInfo.vjsin[0].AssetID, vectorWitness, jsAnchor); } catch (Exception ex) { string strException = ex.Message; throw new InvalidOperationException("JoinSplit Errors"); } if (tx.Inputs == null) { tx.Inputs = new CoinReference[0]; } jsIndex = 0; SnarkDllApi.Witnesses_Clear(vectorWitness); } } #endregion ctx.joinSplitSig = Sodium.PublicKeyAuth.SignDetached(ctx.JsHash.ToArray(), joinSplitPrivKey_); if (!Sodium.PublicKeyAuth.VerifyDetached(ctx.joinSplitSig, ctx.JsHash.ToArray(), joinSplitPubKey_.ToArray())) { throw new InvalidOperationException("Anchor is not correct"); } } else { throw new InvalidOperationException("Anchor is not correct"); } Helper.SignAndShowInformation(tx); } #endregion #region S -> S else if (fromAddrVersion == Wallet.StealthAddressVersion && toAddrVersion == Wallet.StealthAddressVersion) { List <TransactionAttribute> attributes = new List <TransactionAttribute>(); tx = new RingConfidentialTransaction(); tx.Attributes = attributes.ToArray(); if (tx is RingConfidentialTransaction ctx) { List <RCTransactionOutput> rctOutput = new List <RCTransactionOutput>(); Pure.Wallets.StealthKey.StealthKeyPair fromKeyPair = null; foreach (KeyPairBase key in Constant.CurrentWallet.GetKeys()) { if (key is Pure.Wallets.StealthKey.StealthKeyPair rctKey) { if (Wallet.ToStealthAddress(rctKey) == fromAddress) { fromKeyPair = rctKey; } } } if (fromKeyPair == null) { throw new InvalidOperationException("From key is not exist."); } byte[] r = SchnorrNonLinkable.GenerateRandomScalar(); Pure.Cryptography.ECC.ECPoint R = Pure.Cryptography.ECC.ECCurve.Secp256r1.G * r; Pure.Wallets.StealthKey.StealthPubKeys outPubKey = Wallet.ToStealthKeyPair(toAddress).ToStelathPubKeys(); RCTransactionOutput output = new RCTransactionOutput { AssetId = (UInt256)asset.AssetId, PubKey = Pure.Cryptography.ECC.ECPoint.DecodePoint(outPubKey.GenPaymentPubKeyHash(r), Pure.Cryptography.ECC.ECCurve.Secp256r1), Value = amount, ScriptHash = Pure.SmartContract.Contract.CreateRingSignatureRedeemScript(outPubKey.PayloadPubKey, outPubKey.ViewPubKey).ToScriptHash() }; rctOutput.Add(output); ctx.Scripts = new Witness[0]; tx = Constant.CurrentWallet.MakeRCTransaction(ctx, fromAddress, rctOutput, fromKeyPair, r); if (tx == null) { throw new InvalidOperationException("Anchor is not correct"); } } Helper.SignAndShowInformation(tx); } #endregion #region T -> S else if (fromAddrVersion == Wallet.AddressVersion && toAddrVersion == Wallet.StealthAddressVersion) { tx = new RingConfidentialTransaction(); List <TransactionAttribute> attributes = new List <TransactionAttribute>(); tx.Attributes = attributes.ToArray(); if (tx is RingConfidentialTransaction rtx) { List <RCTransactionOutput> rctOutput = new List <RCTransactionOutput>(); byte[] r = SchnorrNonLinkable.GenerateRandomScalar(); Pure.Cryptography.ECC.ECPoint R = Pure.Cryptography.ECC.ECCurve.Secp256r1.G * r; Pure.Wallets.StealthKey.StealthPubKeys outPubKey = Wallet.ToStealthKeyPair(toAddress).ToStelathPubKeys(); RCTransactionOutput output = new RCTransactionOutput { AssetId = (UInt256)asset.AssetId, PubKey = Pure.Cryptography.ECC.ECPoint.DecodePoint(outPubKey.GenPaymentPubKeyHash(r), Pure.Cryptography.ECC.ECCurve.Secp256r1), Value = amount, ScriptHash = Pure.SmartContract.Contract.CreateRingSignatureRedeemScript(outPubKey.PayloadPubKey, outPubKey.ViewPubKey).ToScriptHash() }; rctOutput.Add(output); tx = Constant.CurrentWallet.MakeRCTransaction(rtx, fromAddress, rctOutput, null, r); if (tx == null) { throw new InvalidOperationException("Anchor is not correct"); } } Helper.SignAndShowInformation(tx); } #endregion #region S -> T else if (fromAddrVersion == Wallet.StealthAddressVersion && toAddrVersion == Wallet.AddressVersion) { List <TransactionAttribute> attributes = new List <TransactionAttribute>(); tx = new RingConfidentialTransaction(); tx.Attributes = attributes.ToArray(); if (tx is RingConfidentialTransaction ctx) { List <RCTransactionOutput> rctOutput = new List <RCTransactionOutput>(); Pure.Wallets.StealthKey.StealthKeyPair fromKeyPair = null; foreach (KeyPairBase key in Constant.CurrentWallet.GetKeys()) { if (key is Pure.Wallets.StealthKey.StealthKeyPair rctKey) { if (Wallet.ToStealthAddress(rctKey) == fromAddress) { fromKeyPair = rctKey; } } } if (fromKeyPair == null) { throw new InvalidOperationException("From key is not exist."); } byte[] r = SchnorrNonLinkable.GenerateRandomScalar(); Pure.Cryptography.ECC.ECPoint R = Pure.Cryptography.ECC.ECCurve.Secp256r1.G * r; ctx.Scripts = new Witness[0]; TransactionOutput outPut = new TransactionOutput(); outPut.ScriptHash = Wallet.ToScriptHash(toAddress); outPut.Value = amount; outPut.AssetId = (UInt256)asset.AssetId; tx.Outputs = new TransactionOutput[1]; tx.Outputs[0] = outPut; tx = Constant.CurrentWallet.MakeRCTransaction(ctx, fromAddress, rctOutput, fromKeyPair, r); if (tx == null) { throw new InvalidOperationException("Anchor is not correct"); } } Helper.SignAndShowInformation(tx); } #endregion }
private bool OnSendCommand(string[] args) { if (args.Length < 4 || args.Length > 5) { Console.WriteLine("error"); return(true); } if (Program.Wallet == null) { Console.WriteLine("You have to open the wallet first."); return(true); } using (SecureString password = ReadSecureString("password")) { if (password.Length == 0) { Console.WriteLine("cancelled"); return(true); } if (!Program.Wallet.VerifyPassword(password)) { Console.WriteLine("Incorrect password"); return(true); } } UInt256 assetId; switch (args[1].ToLower()) { case "neo": case "ans": assetId = Blockchain.SystemShare.Hash; break; case "gas": case "anc": assetId = Blockchain.SystemCoin.Hash; break; default: assetId = UInt256.Parse(args[1]); break; } UInt160 scriptHash = Wallet.ToScriptHash(args[2]); bool isSendAll = string.Equals(args[3], "all", StringComparison.OrdinalIgnoreCase); ContractTransaction tx; if (isSendAll) { Coin[] coins = Program.Wallet.FindUnspentCoins().Where(p => p.Output.AssetId.Equals(assetId)).ToArray(); tx = new ContractTransaction { Attributes = new TransactionAttribute[0], Inputs = coins.Select(p => p.Reference).ToArray(), Outputs = new[] { new TransactionOutput { AssetId = assetId, Value = coins.Sum(p => p.Output.Value), ScriptHash = scriptHash } } }; } else { if (!Fixed8.TryParse(args[3], out Fixed8 amount)) { Console.WriteLine("Incorrect Amount Format"); return(true); } if (amount.GetData() % (long)Math.Pow(10, 8 - Blockchain.Default.GetAssetState(assetId).Precision) != 0) { Console.WriteLine("Incorrect Amount Precision"); return(true); } Fixed8 fee = args.Length >= 5 ? Fixed8.Parse(args[4]) : Fixed8.Zero; tx = Program.Wallet.MakeTransaction(new ContractTransaction { Outputs = new[] { new TransactionOutput { AssetId = assetId, Value = amount, ScriptHash = scriptHash } } }, fee: fee); if (tx == null) { Console.WriteLine("Insufficient funds"); return(true); } } SignatureContext context = new SignatureContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Scripts = context.GetScripts(); Program.Wallet.SaveTransaction(tx); LocalNode.Relay(tx); Console.WriteLine($"TXID: {tx.Hash}"); } else { Console.WriteLine("SignatureContext:"); Console.WriteLine(context.ToString()); } return(true); }
public void DoWork() { Global.AssetDescriptor asset = Asset as Global.AssetDescriptor; string fromAddress = FromAddr; string toAddress = ToAddr; string strAmount = Amount; byte toAddrVersion; byte fromAddrVersion; if (asset == null) { return; } if (!Fixed8.TryParse(strAmount, out Fixed8 amount)) { return; } if (amount == Fixed8.Zero) { return; } if (amount.GetData() % (long)Math.Pow(10, 8 - (Asset as Global.AssetDescriptor).Precision) != 0) { return; } try { fromAddrVersion = Wallet.GetAddressVersion(fromAddress); toAddrVersion = Wallet.GetAddressVersion(toAddress); } catch { return; } Transaction tx; if (toAddrVersion == Wallet.AddressVersion && fromAddrVersion == Wallet.AddressVersion) { List <TransactionAttribute> attributes = new List <TransactionAttribute>(); tx = new ContractTransaction(); //if (!string.IsNullOrEmpty(remark)) // attributes.Add(new TransactionAttribute // { // Usage = TransactionAttributeUsage.Remark, // Data = Encoding.UTF8.GetBytes(remark) // }); tx.Attributes = attributes.ToArray(); TransactionOutput outPut = new TransactionOutput(); outPut.ScriptHash = Wallet.ToScriptHash(toAddress); outPut.Value = amount; outPut.AssetId = (UInt256)asset.AssetId; tx.Outputs = new TransactionOutput[1]; tx.Outputs[0] = outPut; if (tx is ContractTransaction ctx) { tx = Constant.CurrentWallet.MakeTransactionFrom(ctx, fromAddress); } /* * if (tx is InvocationTransaction itx) * { * using (InvokeContractDialog dialog = new InvokeContractDialog(itx)) * { * if (dialog.ShowDialog() != DialogResult.OK) return; * tx = dialog.GetTransaction(); * } * } */ FormUI.Helper.SignAndShowInformation(tx); } else if (fromAddrVersion == Wallet.AddressVersion && toAddrVersion == Wallet.AnonymouseAddressVersion) { UInt256 joinSplitPubKey_; byte[] joinSplitPrivKey_; List <TransactionAttribute> attributes = new List <TransactionAttribute>(); tx = new AnonymousContractTransaction(); tx.Attributes = attributes.ToArray(); Sodium.KeyPair keyPair; keyPair = Sodium.PublicKeyAuth.GenerateKeyPair(); joinSplitPubKey_ = new UInt256(keyPair.PublicKey); joinSplitPrivKey_ = keyPair.PrivateKey; ((AnonymousContractTransaction)tx).joinSplitPubKey = joinSplitPubKey_; AsyncJoinSplitInfo info = new AsyncJoinSplitInfo(); info.vpub_old = new Fixed8(0); info.vpub_new = new Fixed8(0); JSOutput jsOut = new JSOutput(Wallet.ToPaymentAddress(toAddress), amount, (UInt256)asset.AssetId); info.vjsout.Add(jsOut); info.vpub_old += amount; if (tx is AnonymousContractTransaction ctx) { tx = Constant.CurrentWallet.MakeTandATransaction(ctx, fromAddress, info); if (tx is AnonymousContractTransaction ctx_) { IntPtr w = SnarkDllApi.Witnesses_Create(); IntPtr ptrRoot = SnarkDllApi.GetCMRoot(Blockchain.Default.GetCmMerkleTree()); byte[] byRoot = new byte[32]; System.Runtime.InteropServices.Marshal.Copy(ptrRoot, byRoot, 0, 32); UInt256 anchor = new UInt256(byRoot); tx = Constant.CurrentWallet.Perform_JoinSplit(ctx_, info, joinSplitPubKey_, joinSplitPrivKey_, (UInt256)asset.AssetId, w, anchor); /* * int dstOffset = 0; * byte[] byJsBody = new byte[ctx_.byJoinSplit.GetListLength()]; * for (int index = 0; index < ctx_.byJoinSplit.Count; index++) * { * Buffer.BlockCopy(ctx_.byJoinSplit[index], 0, byJsBody, dstOffset, ctx_.byJoinSplit[index].Length); * dstOffset += ctx_.byJoinSplit[index].Length; * } * * UInt256 jsHash = new UInt256(Crypto.Default.Hash256(byJsBody)); */ ctx_.joinSplitSig = Sodium.PublicKeyAuth.SignDetached(ctx.JsHash.ToArray(), joinSplitPrivKey_); if (!Sodium.PublicKeyAuth.VerifyDetached(ctx_.joinSplitSig, ctx.JsHash.ToArray(), joinSplitPubKey_.ToArray())) { return; } } } FormUI.Helper.SignAndShowInformation(tx); } else if (fromAddrVersion == Wallet.AnonymouseAddressVersion && toAddrVersion == Wallet.AddressVersion) { UInt256 joinSplitPubKey_; byte[] joinSplitPrivKey_; List <TransactionAttribute> attributes = new List <TransactionAttribute>(); tx = new AnonymousContractTransaction(); Fixed8 vpubNewTarget = Fixed8.Zero; Fixed8 totalAmount = amount; tx.Attributes = attributes.ToArray(); Sodium.KeyPair keyPair; keyPair = Sodium.PublicKeyAuth.GenerateKeyPair(); joinSplitPubKey_ = new UInt256(keyPair.PublicKey); joinSplitPrivKey_ = keyPair.PrivateKey; ((AnonymousContractTransaction)tx).joinSplitPubKey = joinSplitPubKey_; // Do process the transparent outputs. TransactionOutput outPut = new TransactionOutput(); outPut.ScriptHash = Wallet.ToScriptHash(toAddress); outPut.Value = amount; outPut.AssetId = (UInt256)asset.AssetId; tx.Outputs = new TransactionOutput[1]; tx.Outputs[0] = outPut; tx.Scripts = new Witness[0]; vpubNewTarget = amount; AsyncJoinSplitInfo info = new AsyncJoinSplitInfo(); info.vpub_old = Fixed8.Zero; info.vpub_new = Fixed8.Zero; Fixed8 jsInputValue = Fixed8.Zero; IntPtr ptrRoot = SnarkDllApi.GetCMRoot(Blockchain.Default.GetCmMerkleTree()); byte[] byRoot = new byte[32]; System.Runtime.InteropServices.Marshal.Copy(ptrRoot, byRoot, 0, 32); UInt256 jsAnchor = new UInt256(byRoot); if (tx is AnonymousContractTransaction ctx) { tx = Constant.CurrentWallet.MakeAandTTransaction(ctx, fromAddress, info); IntPtr vectorWitness = SnarkDllApi.Witnesses_Create(); int jsIndex = 0; Fixed8 current_inputed_amount = Fixed8.Zero; Fixed8 rest_amount = totalAmount; for (int i = 0; i < info.vjsin.Count; i++) { IntPtr witness = SnarkDllApi.CmWitness_Create(); SnarkDllApi.SetCMWitnessFromBinary(witness, info.vjsin[i].witness, info.vjsin[i].witness.Length); SnarkDllApi.Witnesses_Add(vectorWitness, witness); IntPtr ptrWitness = SnarkDllApi.GetCMRootFromWitness(witness); byte[] byWRoot = new byte[32]; System.Runtime.InteropServices.Marshal.Copy(ptrRoot, byWRoot, 0, 32); UInt256 wAnchor = new UInt256(byWRoot); if (jsAnchor != wAnchor) { throw new InvalidOperationException("Anchor is not correct"); } current_inputed_amount += info.vjsin[i].note.value; jsIndex++; if (jsIndex == 2 && i != info.vjsin.Count - 1) { AsyncJoinSplitInfo jsInfo = new AsyncJoinSplitInfo(); jsInfo.vjsin.Add(info.vjsin[i - 1]); jsInfo.vjsin.Add(info.vjsin[i]); jsInfo.notes.Add(info.notes[i - 1]); jsInfo.notes.Add(info.notes[i]); rest_amount -= jsInfo.notes[0].value; rest_amount -= jsInfo.notes[1].value; if (rest_amount > Fixed8.Zero) { jsInfo.vpub_new = info.vjsin[i - 1].note.value + info.vjsin[i].note.value; jsInfo.vpub_old = Fixed8.Zero; } else { //JSOutput jso = new JSOutput(Wallet.ToPaymentAddress(toAddress), jsInputedAmount, (UInt256)asset.AssetId); //JSOutput jso_remain = new JSOutput(Wallet.ToPaymentAddress(fromAddress), -rest_amount, (UInt256)asset.AssetId); //jsInfo.vjsout.Add(jso); //jsInfo.vjsout.Add(jso_remain); } tx = Constant.CurrentWallet.Perform_JoinSplit(ctx, jsInfo, joinSplitPubKey_, joinSplitPrivKey_, (UInt256)asset.AssetId, vectorWitness, jsAnchor); jsIndex = 0; SnarkDllApi.Witnesses_Clear(vectorWitness); } if (i == info.vjsin.Count - 1) { AsyncJoinSplitInfo jsInfo = new AsyncJoinSplitInfo(); Fixed8 jsInputedAmount = Fixed8.Zero; for (int ji = jsIndex - 1; ji > -1; ji--) { jsInfo.vjsin.Add(info.vjsin[i - ji]); jsInfo.notes.Add(info.notes[i - ji]); jsInputedAmount += info.notes[i - ji].value; rest_amount -= info.notes[i - ji].value; } if (rest_amount < Fixed8.Zero) { JSOutput jso_remain = new JSOutput(Wallet.ToPaymentAddress(fromAddress), -rest_amount, (UInt256)asset.AssetId); jsInfo.vpub_new = jsInputedAmount + rest_amount; jsInfo.vpub_old = Fixed8.Zero; jsInfo.vjsout.Add(jso_remain); } tx = Constant.CurrentWallet.Perform_JoinSplit(ctx, jsInfo, joinSplitPubKey_, joinSplitPrivKey_, (UInt256)asset.AssetId, vectorWitness, jsAnchor); if (tx.Inputs == null) { tx.Inputs = new CoinReference[0]; } jsIndex = 0; SnarkDllApi.Witnesses_Clear(vectorWitness); } } /* * int dstOffset = 0; * byte[] byJsBody = new byte[ctx.byJoinSplit.GetListLength()]; * for (int index = 0; index < ctx.byJoinSplit.Count; index++) * { * Buffer.BlockCopy(ctx.byJoinSplit[index], 0, byJsBody, dstOffset, ctx.byJoinSplit[index].Length); * dstOffset += ctx.byJoinSplit[index].Length; * } * * UInt256 jsHash = new UInt256(Crypto.Default.Hash256(byJsBody)); */ //UInt256 tmp_jsHash = ctx.JsHash; ctx.joinSplitSig = Sodium.PublicKeyAuth.SignDetached(ctx.JsHash.ToArray(), joinSplitPrivKey_); if (!Sodium.PublicKeyAuth.VerifyDetached(ctx.joinSplitSig, ctx.JsHash.ToArray(), joinSplitPubKey_.ToArray())) { return; } } FormUI.Helper.SignAndShowInformation(tx); } else if (fromAddrVersion == Wallet.AnonymouseAddressVersion && toAddrVersion == Wallet.AnonymouseAddressVersion) { UInt256 joinSplitPubKey_; byte[] joinSplitPrivKey_; List <TransactionAttribute> attributes = new List <TransactionAttribute>(); tx = new AnonymousContractTransaction(); Fixed8 totalAmount = amount; tx.Scripts = new Witness[0]; tx.Attributes = attributes.ToArray(); Sodium.KeyPair keyPair; keyPair = Sodium.PublicKeyAuth.GenerateKeyPair(); joinSplitPubKey_ = new UInt256(keyPair.PublicKey); joinSplitPrivKey_ = keyPair.PrivateKey; ((AnonymousContractTransaction)tx).joinSplitPubKey = joinSplitPubKey_; AsyncJoinSplitInfo info = new AsyncJoinSplitInfo(); info.vpub_old = Fixed8.Zero; info.vpub_new = Fixed8.Zero; JSOutput jsOut = new JSOutput(Wallet.ToPaymentAddress(toAddress), amount, (UInt256)asset.AssetId); info.vjsout.Add(jsOut); Fixed8 jsInputValue = Fixed8.Zero; IntPtr ptrRoot = SnarkDllApi.GetCMRoot(Blockchain.Default.GetCmMerkleTree()); byte[] byRoot = new byte[32]; System.Runtime.InteropServices.Marshal.Copy(ptrRoot, byRoot, 0, 32); UInt256 jsAnchor = new UInt256(byRoot); if (tx is AnonymousContractTransaction ctx) { tx = Constant.CurrentWallet.MakeAandATransaction(ctx, fromAddress, info); IntPtr vectorWitness = SnarkDllApi.Witnesses_Create(); int jsIndex = 0; Fixed8 current_inputed_amount = Fixed8.Zero; Fixed8 rest_amount = totalAmount; for (int i = 0; i < info.vjsin.Count; i++) { IntPtr witness = SnarkDllApi.CmWitness_Create(); SnarkDllApi.SetCMWitnessFromBinary(witness, info.vjsin[i].witness, info.vjsin[i].witness.Length); SnarkDllApi.Witnesses_Add(vectorWitness, witness); IntPtr ptrWitness = SnarkDllApi.GetCMRootFromWitness(witness); byte[] byWRoot = new byte[32]; System.Runtime.InteropServices.Marshal.Copy(ptrRoot, byWRoot, 0, 32); UInt256 wAnchor = new UInt256(byWRoot); if (jsAnchor != wAnchor) { throw new InvalidOperationException("Anchor is not correct"); } current_inputed_amount += info.vjsin[i].note.value; jsIndex++; if (jsIndex == 2 && i != info.vjsin.Count - 1) { AsyncJoinSplitInfo jsInfo = new AsyncJoinSplitInfo(); jsInfo.vjsin.Add(info.vjsin[i - 1]); jsInfo.vjsin.Add(info.vjsin[i]); jsInfo.notes.Add(info.notes[i - 1]); jsInfo.notes.Add(info.notes[i]); tx = Constant.CurrentWallet.Perform_JoinSplit(ctx, jsInfo, joinSplitPubKey_, joinSplitPrivKey_, (UInt256)asset.AssetId, vectorWitness, jsAnchor); jsIndex = 0; SnarkDllApi.Witnesses_Clear(vectorWitness); } if (i == info.vjsin.Count - 1) { AsyncJoinSplitInfo jsInfo = new AsyncJoinSplitInfo(); Fixed8 jsInputedAmount = Fixed8.Zero; for (int ji = jsIndex - 1; ji > -1; ji--) { jsInfo.vjsin.Add(info.vjsin[i - ji]); jsInfo.notes.Add(info.notes[i - ji]); jsInputedAmount += info.notes[i - ji].value; rest_amount -= info.notes[i - ji].value; } for (int jo = 0; jo < info.vjsout.Count; jo++) { jsInfo.vjsout.Add(info.vjsout[jo]); } try { tx = Constant.CurrentWallet.Perform_JoinSplit(ctx, jsInfo, joinSplitPubKey_, joinSplitPrivKey_, (UInt256)asset.AssetId, vectorWitness, jsAnchor); } catch (Exception ex) { string strException = ex.Message; } if (tx.Inputs == null) { tx.Inputs = new CoinReference[0]; } jsIndex = 0; SnarkDllApi.Witnesses_Clear(vectorWitness); } } /* * int dstOffset = 0; * byte[] byJsBody = new byte[ctx.byJoinSplit.GetListLength()]; * for (int index = 0; index < ctx.byJoinSplit.Count; index++) * { * Buffer.BlockCopy(ctx.byJoinSplit[index], 0, byJsBody, dstOffset, ctx.byJoinSplit[index].Length); * dstOffset += ctx.byJoinSplit[index].Length; * } * * UInt256 jsHash = new UInt256(Crypto.Default.Hash256(byJsBody)); */ ctx.joinSplitSig = Sodium.PublicKeyAuth.SignDetached(ctx.JsHash.ToArray(), joinSplitPrivKey_); if (!Sodium.PublicKeyAuth.VerifyDetached(ctx.joinSplitSig, ctx.JsHash.ToArray(), joinSplitPubKey_.ToArray())) { return; } } FormUI.Helper.SignAndShowInformation(tx); } }
public void RunTask(string[] chainHashList) { int chainNum = chainHashList.Length; Random rnd = new Random(); TimeSpan oneSecond = TimeSpan.FromSeconds(1); int idx = 0; int total = 0; int cc = concurrencyCount; int lastWaiting = 0; int pendingNum = 0; waitingNum = 0; error = 0; while (true) { if (cancelTokenSource.IsCancellationRequested) { Console.WriteLine("停止发送交易."); break; } if (transferCount > 0) { if (total >= transferCount && pendingNum == 0 && waitingNum == 0) { Console.WriteLine($"round:{++idx}, total:{total}, tx:0, pending:{pendingNum}, waiting:{waitingNum}, error:{error}"); break; } cc = Math.Min(transferCount - total, cc); } Console.WriteLine($"round:{++idx}, total:{total}, tx:{cc}, pending:{pendingNum}, waiting:{waitingNum}, error:{error}"); lastWaiting = waitingNum; if (cc > 0) { Interlocked.Add(ref pendingNum, cc); Interlocked.Add(ref total, cc); } DateTime dt = DateTime.Now; for (int i = 0; i < cc; i++) { int j = i; Task.Run(() => { Random rd = new Random(); int index = rd.Next(0, chainNum); string chainHash = chainHashList[index]; Interlocked.Decrement(ref pendingNum); Fixed8 price = Config.GasPrice; if (randomGasPrice) Fixed8.TryParse((rnd.Next(1, 1000) * 0.00001).ToString(), out price); CallTransfer(chainHash, randomTargetAddress ? GetRandomTargetAddress(rnd) : targetAddress, price); }); } TimeSpan span = DateTime.Now - dt; if (span < oneSecond) { Thread.Sleep(oneSecond - span); } } }
private bool OnSendCommand(string[] args) { if (args.Length < 4 || args.Length > 5) { Console.WriteLine("error"); return(true); } if (NoWallet()) { return(true); } string password = ReadUserInput("password", true); if (password.Length == 0) { Console.WriteLine("cancelled"); return(true); } if (!Program.Wallet.VerifyPassword(password)) { Console.WriteLine("Incorrect password"); return(true); } UIntBase assetId; switch (args[1].ToLower()) { case "krona": case "krn": assetId = Blockchain.GoverningToken.Hash; break; default: assetId = UIntBase.Parse(args[1]); break; } UInt160 scriptHash = args[2].ToScriptHash(); bool isSendAll = string.Equals(args[3], "all", StringComparison.OrdinalIgnoreCase); Transaction tx; if (isSendAll) { Coin[] coins = Program.Wallet.FindUnspentCoins().Where(p => p.Output.AssetId.Equals(assetId)).ToArray(); tx = new P2PTransaction { Attributes = new TransactionAttribute[0], Inputs = coins.Select(p => p.Reference).ToArray(), Outputs = new[] { new TransactionOutput { AssetId = (UInt256)assetId, Value = coins.Sum(p => p.Output.Value), ScriptHash = scriptHash } } }; ContractParametersContext context = new ContractParametersContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Witnesses = context.GetWitnesses(); Program.Wallet.ApplyTransaction(tx); system.LocalNode.Tell(new LocalNode.Relay { Inventory = tx }); Console.WriteLine($"TXID: {tx.Hash}"); } else { Console.WriteLine("SignatureContext:"); Console.WriteLine(context.ToString()); } } else { AssetDescriptor descriptor = new AssetDescriptor(assetId); if (!BigDecimal.TryParse(args[3], descriptor.Decimals, out BigDecimal amount) || amount.Sign <= 0) { Console.WriteLine("Incorrect Amount Format"); return(true); } Fixed8 fee = Fixed8.Zero; if (args.Length >= 5) { if (!Fixed8.TryParse(args[4], out fee) || fee < Fixed8.Zero) { Console.WriteLine("Incorrect Fee Format"); return(true); } } tx = Program.Wallet.MakeTransaction(null, new[] { new TransferOutput { AssetId = assetId, Value = amount, ScriptHash = scriptHash } }, fee: fee); if (tx == null) { Console.WriteLine("Insufficient funds"); return(true); } ContractParametersContext context = new ContractParametersContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Witnesses = context.GetWitnesses(); if (tx.Size > 1024) { Fixed8 calFee = Fixed8.FromDecimal(tx.Size * 0.00001m + 0.001m); if (fee < calFee) { fee = calFee; tx = Program.Wallet.MakeTransaction(null, new[] { new TransferOutput { AssetId = assetId, Value = amount, ScriptHash = scriptHash } }, fee: fee); if (tx == null) { Console.WriteLine("Insufficient funds"); return(true); } context = new ContractParametersContext(tx); Program.Wallet.Sign(context); tx.Witnesses = context.GetWitnesses(); } } Program.Wallet.ApplyTransaction(tx); system.LocalNode.Tell(new LocalNode.Relay { Inventory = tx }); Console.WriteLine($"TXID: {tx.Hash}"); } else { Console.WriteLine("SignatureContext:"); Console.WriteLine(context.ToString()); } } return(true); }
public string GetErrorMessage() { string ret = ""; if (cmb_from.Text.Length == 0) { ret = StringTable.DATA[iLang, 58]; return(ret); } try { Pure.Wallets.Wallet.GetAddressVersion(cmb_from.Text); } catch { ret = StringTable.DATA[iLang, 59]; return(ret); } if (txb_recieve_addr.Text.Length == 0) { ret = StringTable.DATA[iLang, 60]; return(ret); } if (txb_recieve_addr.Text == cmb_from.Text) { ret = StringTable.DATA[iLang, 61]; return(ret); } try { Pure.Wallets.Wallet.GetAddressVersion(txb_recieve_addr.Text); } catch { ret = StringTable.DATA[iLang, 62]; return(ret); } if (cmb_assets.SelectedItem == null) { ret = StringTable.DATA[iLang, 63]; return(ret); } if (txb_amount.Text.Length == 0) { ret = StringTable.DATA[iLang, 64]; return(ret); } if (!Fixed8.TryParse(txb_amount.Text, out Fixed8 amount)) { ret = StringTable.DATA[iLang, 65]; return(ret); } if (amount == Fixed8.Zero) { ret = StringTable.DATA[iLang, 66]; return(ret); } Fixed8 max_balance = Fixed8.Zero; string FromAddr = cmb_from.Text; string MaxAmount = "0"; Global.AssetDescriptor asset = cmb_assets.SelectedItem as Global.AssetDescriptor; if (asset == null) { ret = StringTable.DATA[iLang, 67]; return(ret); } UInt256 AssetID = new UInt256(asset.AssetId.ToArray()); if (AddressAssetsImp.getInstance().GetList().ContainsKey(FromAddr)) { if (AddressAssetsImp.getInstance().GetList()[FromAddr].Assets.ContainsKey(AssetID)) { MaxAmount = AddressAssetsImp.getInstance().GetList()[FromAddr].Assets[AssetID]; } } max_balance = Fixed8.One * Fixed8.Parse(MaxAmount); if (amount > max_balance) { ret = StringTable.DATA[iLang, 68]; return(ret); } if (Wallet.GetAddressVersion(cmb_from.Text) == Wallet.AnonymouseAddressVersion || Wallet.GetAddressVersion(txb_recieve_addr.Text) == Wallet.AnonymouseAddressVersion) { if (Constant.bSnarksParamLoaded == false) { ret = StringTable.DATA[iLang, 69]; return(ret); } } return(ret); }
public string GetErrorMessage() { string ret = ""; if (txb_from_address.Text.Length == 0) { ret = "You didn't input the from wallet path!\r\nPlease input the from wallet path."; return(ret); } try { Pure.Wallets.Wallet.GetAddressVersion(txb_from_address.Text); } catch { ret = "The from wallet format is not correct!"; return(ret); } if (txb_recv_addr.Text.Length == 0) { ret = "You didn't input the wallet path!\r\nPlease input the wallet path."; return(ret); } try { Pure.Wallets.Wallet.GetAddressVersion(txb_recv_addr.Text); } catch { ret = "The wallet format is not correct!"; return(ret); } if (cmb_assets.SelectedItem == null) { ret = "You didn't select the assets type!\r\nPlease select the asset type."; return(ret); } if (txb_amount.Text.Length == 0) { ret = "You didn't input the amount!\r\nPlease input the amount."; return(ret); } if (!Fixed8.TryParse(txb_amount.Text, out Fixed8 amount)) { ret = "Please input the correct amount!\r\nAmount type is not correct."; return(ret); } if (amount == Fixed8.Zero) { ret = "Send amount must be bigger than zero!"; return(ret); } Fixed8 max_balance = Fixed8.Zero; if (((AssetDescriptor)cmb_assets.SelectedItem).AssetName == "QRS") { max_balance = qrs_balance; } else if (((AssetDescriptor)cmb_assets.SelectedItem).AssetName == "QRG") { max_balance = qrg_balance; } if (amount > max_balance) { ret = "The amount is unsufficient!"; return(ret); } return(ret); }
public void RunTask(string chainHash, Blockchain blockchain) { Random rnd = new Random(); TimeSpan oneSecond = TimeSpan.FromSeconds(1); Fixed8 gasPrice = Fixed8.FromDecimal(0.00001m); int idx = 0; int total = 0; int cc = concurrencyCount; int lastWaiting = 0; int pendingNum = 0; waitingNum = 0; error = 0; while (true) { if (cancelTokenSource.IsCancellationRequested) { Console.WriteLine("Stress testing stopped."); break; } if (transferCount > 0) { if (total >= transferCount && pendingNum == 0 && waitingNum == 0) { Console.WriteLine($"round:{++idx}, total:{total}, tx:0, pending:{pendingNum}, waiting:{waitingNum}, error:{error}"); break; } cc = Math.Min(transferCount - total, concurrencyCount); if (preventOverflow) { int mempool_count = blockchain.GetMemoryPoolCount(); if (mempool_count + cc + pendingNum + waitingNum >= 50000) { cc = 0; } } } Console.WriteLine($"round:{++idx}, total:{total}, tx:{cc}, pending:{pendingNum}, waiting:{waitingNum}, error:{error}"); lastWaiting = waitingNum; if (cc > 0) { Interlocked.Add(ref pendingNum, cc); Interlocked.Add(ref total, cc); } DateTime dt = DateTime.Now; for (int i = 0; i < cc; i++) { Task.Run(() => { Interlocked.Decrement(ref pendingNum); Fixed8 price = gasPrice; if (randomGasPrice) { Fixed8.TryParse((rnd.Next(1, 1000) * 0.00001).ToString(), out price); } CallTransfer(chainHash, randomTargetAddress ? GetRandomTargetAddress(rnd) : targetAddress, price); }); } TimeSpan span = DateTime.Now - dt; if (span < oneSecond) { Thread.Sleep(oneSecond - span); } } }
private void Event_SendCoinSuccess(object sender, EventArgs e) { Global.AssetDescriptor asset = sendcoinsPan1.GetAsset() as Global.AssetDescriptor; string fromAddress = sendcoinsPan1.GetFromAddress(); string toAddress = sendcoinsPan1.GetRecieveAddress(); string strAmount = sendcoinsPan1.GetAmount(); byte toAddrVersion; byte fromAddrVersion; if (asset == null) { return; } if (!Fixed8.TryParse(strAmount, out Fixed8 amount)) { return; } if (amount == Fixed8.Zero) { return; } if (amount.GetData() % (long)Math.Pow(10, 8 - (sendcoinsPan1.GetAsset() as Global.AssetDescriptor).Precision) != 0) { return; } try { fromAddrVersion = Wallet.GetAddressVersion(fromAddress); toAddrVersion = Wallet.GetAddressVersion(toAddress); } catch { return; } Transaction tx; if (toAddrVersion == Wallet.AddressVersion && fromAddrVersion == Wallet.AddressVersion) { List <TransactionAttribute> attributes = new List <TransactionAttribute>(); tx = new ContractTransaction(); //if (!string.IsNullOrEmpty(remark)) // attributes.Add(new TransactionAttribute // { // Usage = TransactionAttributeUsage.Remark, // Data = Encoding.UTF8.GetBytes(remark) // }); tx.Attributes = attributes.ToArray(); TransactionOutput outPut = new TransactionOutput(); outPut.ScriptHash = Wallet.ToScriptHash(toAddress); outPut.Value = amount; outPut.AssetId = (UInt256)asset.AssetId; tx.Outputs = new TransactionOutput[1]; tx.Outputs[0] = outPut; if (tx is ContractTransaction ctx) { tx = Constant.CurrentWallet.MakeTransactionFrom(ctx, fromAddress); } /* * if (tx is InvocationTransaction itx) * { * using (InvokeContractDialog dialog = new InvokeContractDialog(itx)) * { * if (dialog.ShowDialog() != DialogResult.OK) return; * tx = dialog.GetTransaction(); * } * } */ Helper.SignAndShowInformation(tx); } else if (toAddrVersion == Wallet.AnonymouseAddressVersion) { UInt256 joinSplitPubKey_; byte[] joinSplitPrivKey_; List <TransactionAttribute> attributes = new List <TransactionAttribute>(); tx = new AnonymousContractTransaction(); tx.Attributes = attributes.ToArray(); Sodium.KeyPair keyPair; keyPair = Sodium.PublicKeyAuth.GenerateKeyPair(); joinSplitPubKey_ = new UInt256(keyPair.PublicKey); joinSplitPrivKey_ = keyPair.PrivateKey; ((AnonymousContractTransaction)tx).joinSplitPubKey = joinSplitPubKey_; AsyncJoinSplitInfo info = new AsyncJoinSplitInfo(); info.vpub_old = new Fixed8(0); info.vpub_new = new Fixed8(0); JSOutput jsOut = new JSOutput(Wallet.ToPaymentAddress(toAddress), amount, (UInt256)asset.AssetId); info.vjsout.Add(jsOut); info.vpub_old += amount; if (tx is AnonymousContractTransaction ctx) { tx = Constant.CurrentWallet.MakeTandATransaction(ctx, fromAddress, info); if (tx is AnonymousContractTransaction ctx_) { IntPtr w = SnarkDllApi.Witnesses_Create(); UInt256 anchor = new UInt256(); tx = Constant.CurrentWallet.Perform_JoinSplit(ctx_, info, joinSplitPubKey_, joinSplitPrivKey_, (UInt256)asset.AssetId, w, anchor); } } Helper.SignAndShowInformation(tx); } }