/// <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())); }
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); } }
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)"); }
/// <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(); }
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); }
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 } }