Example #1
0
        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);
            }
        }
Example #4
0
        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;
        }
Example #5
0
        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.
        }
Example #6
0
        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.
        }
Example #7
0
        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.
        }
Example #8
0
        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);
        }
Example #9
0
        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();
        }
Example #10
0
        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();
        }
Example #12
0
 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);
        }
Example #14
0
        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
        }
Example #15
0
        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);
        }
Example #16
0
        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);
                }
            }
        }
Example #18
0
        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);
        }
Example #19
0
        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);
        }
Example #20
0
        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);
        }
Example #21
0
        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);
                }
            }
        }
Example #22
0
        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);
            }
        }