Beispiel #1
0
        /// <summary>
        ///     Returns base64-encoded TransactionEnvelope XDR object. Transaction need to have at least one signature.
        /// </summary>
        /// <returns></returns>
        public string ToEnvelopeXdrBase64()
        {
            var envelope = ToEnvelopeXdr();
            var writer   = new XdrDataOutputStream();

            TransactionEnvelope.Encode(writer, envelope);

            return(Convert.ToBase64String(writer.ToArray()));
        }
Beispiel #2
0
        public static string BackAndForthXdrStreaming(string inputString)
        {
            var xdrOutputStream = new XdrDataOutputStream();

            xdrOutputStream.WriteString(inputString);

            var xdrByteOutput = xdrOutputStream.ToArray();

            //XDR back to string
            var xdrInputStream = new XdrDataInputStream(xdrByteOutput);
            var outputString   = xdrInputStream.ReadString();

            return(outputString);
        }
        public async Task WithdrawalQuantumTest(double amount, bool hasWithdrawal, bool useFakeSigner, Type excpectedException)
        {
            var outputStream = new XdrDataOutputStream();
            var txBuilder    = new TransactionBuilder(new AccountResponse(TestEnvironment.Client1KeyPair.AccountId, 1));

            txBuilder.SetFee(10_000);

            txBuilder.AddOperation(new PaymentOperation.Builder(TestEnvironment.Client1KeyPair, new AssetTypeNative(), (amount / AssetsHelper.StroopsPerAsset).ToString("0.##########", CultureInfo.InvariantCulture)).SetSourceAccount(TestEnvironment.AlphaKeyPair).Build());
            txBuilder.AddTimeBounds(new stellar_dotnet_sdk.TimeBounds(maxTime: DateTimeOffset.UtcNow.AddSeconds(60)));
            var tx = txBuilder.Build();

            stellar_dotnet_sdk.xdr.Transaction.Encode(outputStream, tx.ToXdrV1());

            var account    = Global.AccountStorage.GetAccount(TestEnvironment.Client1KeyPair);
            var withdrawal = new WithdrawalRequest
            {
                Account        = account.Account.Id,
                RequestId      = 1,
                TransactionXdr = outputStream.ToArray(),
                AccountWrapper = account
            };

            var envelope = withdrawal.CreateEnvelope();

            envelope.Sign(useFakeSigner ? TestEnvironment.Client2KeyPair : TestEnvironment.Client1KeyPair);

            if (!Global.IsAlpha)
            {
                var quantum = new RequestQuantum {
                    Apex = Global.QuantumStorage.CurrentApex + 1, RequestEnvelope = envelope, Timestamp = DateTime.UtcNow.Ticks
                };
                envelope = quantum.CreateEnvelope();
                envelope.Sign(TestEnvironment.AlphaKeyPair);
            }

            var result = await AssertQuantumHandling(envelope, excpectedException);

            if (excpectedException == null)
            {
                Assert.IsTrue(account.HasPendingWithdrawal);

                Assert.IsTrue(account.Account.GetBalance(0).Liabilities == amount);
            }
        }
Beispiel #4
0
        public void XdrOtputStreamPerformanceTest(int rounds, int iterations)
        {
            var testArray = new byte[32];

            Array.Fill(testArray, (byte)100);
            PerfCounter.MeasureTime(() =>
            {
                for (var r = 0; r < rounds; r++)
                {
                    var stream = new XdrDataOutputStream();
                    for (var i = 0; i < iterations; i++)
                    {
                        stream.WriteInt(435);
                        stream.WriteString("oiewurouqwe");
                        stream.WriteVarOpaque(32, testArray);
                    }
                    stream.ToArray();
                }
            }, () => $"({rounds} rounds, {iterations} iterations)");
        }
Beispiel #5
0
        /// <summary>
        ///     Returns signature base.
        /// </summary>
        /// <returns></returns>
        public byte[] SignatureBase()
        {
            if (Network.Current == null)
                throw new NoNetworkSelectedException();

            var writer = new XdrDataOutputStream();

            // Hashed NetworkID
            writer.Write(Network.Current.NetworkId);

            // Envelope Type - 4 bytes
            EnvelopeType.Encode(writer, EnvelopeType.Create(EnvelopeType.EnvelopeTypeEnum.ENVELOPE_TYPE_TX));

            // Transaction XDR bytes
            var txWriter = new XdrDataOutputStream();
            xdr.Transaction.Encode(txWriter, ToXdr());

            writer.Write(txWriter.ToArray());

            return writer.ToArray();
        }
Beispiel #6
0
        public async Task <string> BuildTransactionAsync(Guid operationId, AddressBalance from, string toAddress, string memoText, long amount)
        {
            var fromKeyPair = KeyPair.FromAccountId(from.Address);
            var fromAccount = new Account(fromKeyPair, from.Sequence);

            var toKeyPair = KeyPair.FromAccountId(toAddress);

            var transferableBalance = from.Balance - from.MinBalance;

            Operation operation;

            if (await _horizonService.AccountExists(toAddress))
            {
                if (amount <= transferableBalance)
                {
                    var asset = new AssetTypeNative();
                    operation = new PaymentOperation.Builder(toKeyPair, asset, Operation.FromXdrAmount(amount))
                                .SetSourceAccount(fromKeyPair)
                                .Build();
                }
                else if (!_balanceService.IsDepositBaseAddress(from.Address))
                {
                    operation = new AccountMergeOperation.Builder(toKeyPair)
                                .SetSourceAccount(fromKeyPair)
                                .Build();
                }
                else
                {
                    throw new BusinessException($"It isn't allowed to merge the entire balance from the deposit base into another account! Transfer less funds. transferable={transferableBalance}");
                }
            }
            else
            {
                if (amount <= transferableBalance)
                {
                    operation = new CreateAccountOperation.Builder(toKeyPair, Operation.FromXdrAmount(amount))
                                .SetSourceAccount(fromKeyPair)
                                .Build();
                }
                else
                {
                    throw new BusinessException($"It isn't possible to merge the entire balance into an unused account! Use a destination in existance. transferable={transferableBalance}");
                }
            }

            var builder = new TransactionBuilder(fromAccount)
                          .AddOperation(operation)
                          .SetFee(_appSettings.StellarApiService.OperationFee);

            if (!string.IsNullOrWhiteSpace(memoText))
            {
                var memo = new MemoText(memoText);
                builder = builder.AddMemo(memo);
            }

            var tx = builder.Build();

            var xdr               = tx.ToUnsignedEnvelopeXdr(TransactionBase.TransactionXdrVersion.V1);
            var expirationDate    = (DateTime.UtcNow + _transactionExpirationTime);
            var maxUnixTimeDouble = expirationDate.ToUnixTime() / 1000;//ms to seconds
            var maxTimeUnix       = (ulong)maxUnixTimeDouble;

            xdr.V1.Tx.TimeBounds = new TimeBounds()
            {
                MaxTime = new TimePoint(new Uint64(maxTimeUnix)),
                MinTime = new TimePoint(new Uint64(0)),
            };

            var writer = new XdrDataOutputStream();

            stellar_dotnet_sdk.xdr.TransactionEnvelope.Encode(writer, xdr);
            var xdrBase64 = Convert.ToBase64String(writer.ToArray());

            _log.Info("Transaction has been built", new
            {
                OperationId = operationId,
                From        = from,
                To          = toAddress,
                Memo        = memoText,
                Amount      = amount,
                Fee         = tx.Fee,
                Sequence    = tx.SequenceNumber,
                MaxTimeUnix = maxTimeUnix
            });

            var build = new TxBuild
            {
                OperationId = operationId,
                XdrBase64   = xdrBase64
            };
            await _buildRepository.AddAsync(build);

            return(xdrBase64);
        }
Beispiel #7
0
        public void XdrCompatibilityTest()
        {
            var testArray = new byte[32];

            Array.Fill(testArray, (byte)100);

            //forward compatibility
            var legacyXdrSerializationStream = new XdrDataOutputStream();

            legacyXdrSerializationStream.WriteInt(435);
            legacyXdrSerializationStream.WriteUInt(435);
            legacyXdrSerializationStream.WriteLong(43546345634657565L);
            legacyXdrSerializationStream.WriteDoubleArray(new double[] { 435.15, 64656.11 });
            legacyXdrSerializationStream.WriteString("oiewurouqwe");
            legacyXdrSerializationStream.WriteVarOpaque(32, testArray);

            var bufferReader = new XdrBufferReader(legacyXdrSerializationStream.ToArray());

            Assert.AreEqual(435, bufferReader.ReadInt32());
            Assert.AreEqual((uint)435, bufferReader.ReadUInt32());
            Assert.AreEqual(43546345634657565L, bufferReader.ReadInt64());
            {
                var length = bufferReader.ReadInt32();
                var value  = new double[length];
                for (var i = 0; i < length; i++)
                {
                    value[i] = bufferReader.ReadDouble();
                }
                Assert.AreEqual(new double[] { 435.15, 64656.11 }, value);
            }
            Assert.AreEqual("oiewurouqwe", bufferReader.ReadString());
            Assert.AreEqual(testArray, bufferReader.ReadVariable());

            using var streamReader = new XdrStreamReader(new MemoryStream(legacyXdrSerializationStream.ToArray()));
            Assert.AreEqual(435, streamReader.ReadInt32());
            Assert.AreEqual((uint)435, streamReader.ReadUInt32());
            Assert.AreEqual(43546345634657565L, streamReader.ReadInt64());
            {
                var length = streamReader.ReadInt32();
                var value  = new double[length];
                for (var i = 0; i < length; i++)
                {
                    value[i] = streamReader.ReadDouble();
                }
                Assert.AreEqual(new double[] { 435.15, 64656.11 }, value);
            }
            Assert.AreEqual("oiewurouqwe", streamReader.ReadString());
            Assert.AreEqual(testArray, streamReader.ReadVariable());

            //backward compatibility
            var bufferWriter = new XdrBufferWriter();

            bufferWriter.WriteInt32(435);
            bufferWriter.WriteUInt32((uint)435);
            {
                var arr = new double[] { 435.15, 64656.11 };
                bufferWriter.WriteInt32(arr.Length);
                foreach (var d in arr)
                {
                    bufferWriter.WriteDouble(d);
                }
            }
            bufferWriter.WriteString("oiewurouqwe");
            bufferWriter.WriteVariable(testArray);

            var legacyXdrReader = new XdrDataInputStream(bufferWriter.ToArray());

            Assert.AreEqual(435, legacyXdrReader.ReadInt());
            Assert.AreEqual((uint)435, legacyXdrReader.ReadUInt());
            Assert.AreEqual(new double[] { 435.15, 64656.11 }, legacyXdrReader.ReadDoubleArray());
            Assert.AreEqual("oiewurouqwe", legacyXdrReader.ReadString());
            Assert.AreEqual(testArray, legacyXdrReader.ReadVarOpaque(32));


            using var memoryStream = new MemoryStream();
            var streamWriter = new XdrStreamWriter(memoryStream);

            streamWriter.WriteInt32(435);
            streamWriter.WriteUInt32((uint)435);
            {
                var arr = new double[] { 435.15, 64656.11 };
                streamWriter.WriteInt32(arr.Length);
                foreach (var d in arr)
                {
                    streamWriter.WriteDouble(d);
                }
            }
            streamWriter.WriteString("oiewurouqwe");
            streamWriter.WriteVariable(testArray);
            var res       = memoryStream.ToArray();
            var reference = bufferWriter.ToArray();

            CollectionAssert.AreEqual(reference, res);
        }
        public async Task WithdrawalCleanupQuantumTest(double amount, bool useFakeHash, Type excpectedException)
        {
            var outputStream = new XdrDataOutputStream();
            var txBuilder    = new TransactionBuilder(new AccountResponse(TestEnvironment.Client1KeyPair.AccountId, 1));

            txBuilder.SetFee(10_000);

            txBuilder.AddOperation(new PaymentOperation.Builder(TestEnvironment.Client1KeyPair, new AssetTypeNative(), (amount / AssetsHelper.StroopsPerAsset).ToString("0.##########", CultureInfo.InvariantCulture)).SetSourceAccount(TestEnvironment.AlphaKeyPair).Build());
            txBuilder.AddTimeBounds(new stellar_dotnet_sdk.TimeBounds(maxTime: DateTimeOffset.UtcNow.AddSeconds(60)));
            var tx = txBuilder.Build();

            stellar_dotnet_sdk.xdr.Transaction.Encode(outputStream, tx.ToXdrV1());

            var account = context.AccountStorage.GetAccount(TestEnvironment.Client1KeyPair);

            var acc        = context.AccountStorage.GetAccount(TestEnvironment.Client1KeyPair);
            var withdrawal = new WithdrawalRequest
            {
                Account        = acc.Account.Id,
                RequestId      = 1,
                TransactionXdr = outputStream.ToArray(),
                AccountWrapper = account
            };

            var envelope = withdrawal.CreateEnvelope();

            envelope.Sign(TestEnvironment.Client1KeyPair);

            if (!context.IsAlpha)
            {
                var quantum = new RequestQuantum {
                    Apex = context.QuantumStorage.CurrentApex + 1, RequestEnvelope = envelope, Timestamp = DateTime.UtcNow.Ticks
                };
                envelope = quantum.CreateEnvelope();
                envelope.Sign(TestEnvironment.AlphaKeyPair);
            }

            var result = await AssertQuantumHandling(envelope, null);

            if (result.Status != ResultStatusCodes.Success)
            {
                throw new Exception("Withdrawal creation failed.");
            }

            var cleanup = new WithrawalsCleanupQuantum
            {
                ExpiredWithdrawal = useFakeHash ? new byte[] { } : tx.Hash(),
                Apex = context.QuantumStorage.CurrentApex + 1
            };

            envelope = cleanup.CreateEnvelope();


            if (!context.IsAlpha)
            {
                cleanup.Timestamp = DateTime.UtcNow.Ticks;
                envelope          = cleanup.CreateEnvelope();
                envelope.Sign(TestEnvironment.AlphaKeyPair);
            }

            await AssertQuantumHandling(envelope, excpectedException);

            if (excpectedException == null)
            {
                Assert.IsTrue(!account.HasPendingWithdrawal);

                Assert.AreEqual(account.Account.GetBalance(0).Liabilities, 0);
            }
        }
        public async Task TxCommitQuantumTest(int cursor, int amount, int asset, Type excpectedException)
        {
            context.AppState.State = ApplicationState.Ready;

            long apex = context.QuantumStorage.CurrentApex;

            var client1StartBalanceAmount = (long)0;

            var account1 = context.AccountStorage.GetAccount(TestEnvironment.Client1KeyPair).Account;

            var clientAccountBalance = account1.GetBalance(asset);

            var withdrawalDest = KeyPair.Random();
            var txHash         = new byte[] { };

            if (clientAccountBalance != null && amount > 0)
            {
                client1StartBalanceAmount = clientAccountBalance.Amount;


                context.Constellation.TryFindAssetSettings(asset, out var assetSettings);

                var account   = new stellar_dotnet_sdk.Account(TestEnvironment.Client1KeyPair.AccountId, 1);
                var txBuilder = new TransactionBuilder(account);
                txBuilder.SetFee(10_000);
                txBuilder.AddTimeBounds(new stellar_dotnet_sdk.TimeBounds(DateTimeOffset.UtcNow, new TimeSpan(0, 5, 0)));
                txBuilder.AddOperation(
                    new PaymentOperation.Builder(withdrawalDest, assetSettings.ToAsset(), Amount.FromXdr(amount).ToString())
                    .SetSourceAccount((KeyPair)context.Constellation.Vault)
                    .Build()
                    );
                var tx = txBuilder.Build();
                txHash = tx.Hash();

                var txV1     = tx.ToXdrV1();
                var txStream = new XdrDataOutputStream();
                stellar_dotnet_sdk.xdr.Transaction.Encode(txStream, txV1);

                var accountWrapper = context.AccountStorage.GetAccount(TestEnvironment.Client1KeyPair);

                var withdrawal = new WithdrawalRequest
                {
                    Account        = accountWrapper.Account.Id,
                    TransactionXdr = txStream.ToArray(),
                    RequestId      = DateTime.UtcNow.Ticks,
                    AccountWrapper = accountWrapper
                };

                MessageEnvelope quantum = withdrawal.CreateEnvelope();
                quantum.Sign(TestEnvironment.Client1KeyPair);
                if (!context.IsAlpha)
                {
                    quantum = new RequestQuantum {
                        Apex = ++apex, RequestEnvelope = quantum, Timestamp = DateTime.UtcNow.Ticks
                    }.CreateEnvelope();
                    quantum.Sign(TestEnvironment.AlphaKeyPair);
                }
                //create withdrawal
                await context.QuantumHandler.HandleAsync(quantum);
            }

            var depositAmount = new Random().Next(10, 1000);

            var ledgerNotification = new TxNotification
            {
                TxCursor = (uint)cursor,
                Payments = new List <PaymentBase>
                {
                    new Deposit
                    {
                        Amount      = depositAmount,
                        Destination = TestEnvironment.Client1KeyPair,
                        Asset       = asset
                    },
                    new Withdrawal
                    {
                        TransactionHash = txHash,
                        PaymentResult   = PaymentResults.Success
                    }
                }
            };
            var ledgerNotificationEnvelope = ledgerNotification.CreateEnvelope();

            ledgerNotificationEnvelope.Sign(TestEnvironment.Auditor1KeyPair);

            var ledgerCommitEnv = new TxCommitQuantum
            {
                Source = ledgerNotificationEnvelope,
                Apex   = ++apex
            }.CreateEnvelope();

            if (!context.IsAlpha)
            {
                var msg = ((TxCommitQuantum)ledgerCommitEnv.Message);
                msg.Timestamp   = DateTime.UtcNow.Ticks;
                ledgerCommitEnv = msg.CreateEnvelope().Sign(TestEnvironment.AlphaKeyPair);
            }

            await AssertQuantumHandling(ledgerCommitEnv, excpectedException);

            if (excpectedException == null)
            {
                Assert.AreEqual(context.TxCursorManager.TxCursor, ledgerNotification.TxCursor);

                Assert.AreEqual(account1.GetBalance(asset).Liabilities, 0);
                Assert.AreEqual(account1.GetBalance(asset).Amount, client1StartBalanceAmount - amount + depositAmount); //acc balance + deposit - withdrawal
            }
        }