///<param name="timeBounds">Timebounds for given transaction</param> ///<returns>Returns true if transaction is created more than 10 secods from now</returns> public Boolean TooOld(Stellar.TimeBounds timeBounds) { long now = DateTimeOffset.Now.ToUnixTimeSeconds(); int strictInterval = new Client().StrictInterval; return(now > (timeBounds.MinTime + strictInterval)); }
///<summary>Private: Checks if current time is within transaction timebounds</summary> ///<param name="timeBounds">Timebounds for given transaction</param> ///<returns>Returns true if current time is within transaction time bounds</returns> private Boolean TimeNowCovers(Stellar.TimeBounds timeBounds) { long now = DateTimeOffset.Now.ToUnixTimeSeconds(); return( now >= timeBounds.MinTime && now <= timeBounds.MaxTime ); }
/// <summary> /// Build a challenge transaction you can use for Stellar Web Authentication. /// </summary> /// <param name="serverKeypair">Server signing keypair</param> /// <param name="clientAccountId">The client account id that needs authentication</param> /// <param name="anchorName">The anchor name</param> /// <param name="nonce">48 bytes long cryptographic-quality random data</param> /// <param name="now">The datetime from which the transaction is valid</param> /// <param name="timeout">The transaction lifespan</param> /// <param name="network">The network the transaction will be submitted to</param> /// <returns>The challenge transaction</returns> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="ArgumentException"></exception> public static Transaction BuildChallengeTransaction(KeyPair serverKeypair, string clientAccountId, string anchorName, byte[] nonce = null, DateTimeOffset?now = null, TimeSpan?timeout = null, Network network = null) { if (serverKeypair is null) { throw new ArgumentNullException(nameof(serverKeypair)); } if (string.IsNullOrEmpty(clientAccountId)) { throw new ArgumentNullException(nameof(clientAccountId)); } if (string.IsNullOrEmpty(anchorName)) { throw new ArgumentNullException(nameof(anchorName)); } if (nonce is null) { var rng = NSec.Cryptography.RandomGenerator.Default; // A base64 digit represents 6 bites, to generate 64 bytes long base64 encoded strings // we need 64 * 6 / 8 bytes. nonce = rng.GenerateBytes(48); } else if (nonce.Length != 48) { throw new ArgumentException("nonce must be 48 bytes long"); } network = network ?? Network.Current; var validFrom = now ?? DateTimeOffset.Now; var validTo = validFrom.Add(timeout ?? TimeSpan.FromMinutes(5.0)); var sourceAccountKeypair = KeyPair.FromAccountId(clientAccountId); // Sequence number is incremented by 1 before building the transaction, set it to -1 to have 0 var serverAccount = new Account(serverKeypair.AccountId, -1); var manageDataKey = $"{anchorName} auth"; var manageDataValue = Encoding.UTF8.GetBytes(Convert.ToBase64String(nonce)); var timeBounds = new TimeBounds(validFrom, validTo); var operation = new ManageDataOperation.Builder(manageDataKey, manageDataValue) .SetSourceAccount(sourceAccountKeypair) .Build(); var tx = new Transaction.Builder(serverAccount) .AddTimeBounds(timeBounds) .AddOperation(operation) .Build(); tx.Sign(serverKeypair, network); return(tx); }
/// <summary> /// Adds a time-bounds to this transaction. /// See: https://www.stellar.org/developers/learn/concepts/transactions.html /// </summary> /// <param name="timeBounds">timeBounds</param> /// <returns>Builder object so you can chain methods.</returns> public Builder AddTimeBounds(TimeBounds timeBounds) { if (_timeBounds != null) { throw new ArgumentException("TimeBounds has been already added.", nameof(timeBounds)); } _timeBounds = timeBounds ?? throw new ArgumentNullException(nameof(timeBounds), "timeBounds cannot be null"); return(this); }
private static bool ValidateTimeBounds(TimeBounds timeBounds, DateTimeOffset now) { if (timeBounds is null) { return(false); } if (timeBounds.MinTime == 0 || timeBounds.MaxTime == 0) { return(false); } var unixNow = now.ToUnixTimeSeconds(); return(timeBounds.MinTime <= unixNow && unixNow <= timeBounds.MaxTime); }
public Transaction(IAccountId sourceAccount, uint fee, long sequenceNumber, Operation[] operations, Memo memo, TimeBounds timeBounds) { SourceAccount = sourceAccount ?? throw new ArgumentNullException(nameof(sourceAccount), "sourceAccount cannot be null"); Fee = fee; SequenceNumber = sequenceNumber; Operations = operations ?? throw new ArgumentNullException(nameof(operations), "operations cannot be null"); if (operations.Length == 0) { throw new ArgumentNullException(nameof(operations), "At least one operation required"); } Memo = memo ?? Memo.None(); TimeBounds = timeBounds; }
private Transaction(KeyPair sourceAccount, long sequenceNumber, Operation[] operations, Memo memo, TimeBounds timeBounds) { SourceAccount = sourceAccount ?? throw new ArgumentNullException(nameof(sourceAccount), "sourceAccount cannot be null"); SequenceNumber = sequenceNumber; Operations = operations ?? throw new ArgumentNullException(nameof(operations), "operations cannot be null"); if (operations.Length == 0) { throw new ArgumentNullException(nameof(operations), "At least one operation required"); } Fee = operations.Length * BaseFee; Signatures = new List <DecoratedSignature>(); Memo = memo ?? Memo.None(); TimeBounds = timeBounds; }
/// <summary> /// Generates Transaction XDR object. /// </summary> /// <returns></returns> public xdr.Transaction ToXdr() { // fee var fee = new Uint32 { InnerValue = Fee }; // sequenceNumber var sequenceNumberUint = new Uint64 { InnerValue = SequenceNumber }; var sequenceNumber = new SequenceNumber { InnerValue = sequenceNumberUint }; // sourceAccount var sourceAccount = new AccountID { InnerValue = SourceAccount.XdrPublicKey }; // operations var operations = new xdr.Operation[Operations.Length]; for (var i = 0; i < Operations.Length; i++) { operations[i] = Operations[i].ToXdr(); } // ext var ext = new xdr.Transaction.TransactionExt { Discriminant = 0 }; var transaction = new xdr.Transaction { Fee = fee, SeqNum = sequenceNumber, SourceAccount = sourceAccount, Operations = operations, Memo = Memo.ToXdr(), TimeBounds = TimeBounds?.ToXdr(), Ext = ext }; return(transaction); }
public override bool Equals(Object o) { if (this == o) { return(true); } if (o == null || GetType() != o.GetType()) { return(false); } TimeBounds that = (TimeBounds)o; if (MinTime != that.MinTime) { return(false); } return(MaxTime == that.MaxTime); }
public static Transaction FromEnvelopeXdr(TransactionEnvelope envelope) { xdr.Transaction transactionXdr = envelope.Tx; var fee = transactionXdr.Fee.InnerValue; KeyPair sourceAccount = KeyPair.FromXdrPublicKey(transactionXdr.SourceAccount.InnerValue); long sequenceNumber = transactionXdr.SeqNum.InnerValue.InnerValue; Memo memo = Memo.FromXdr(transactionXdr.Memo); TimeBounds timeBounds = TimeBounds.FromXdr(transactionXdr.TimeBounds); Operation[] operations = new Operation[transactionXdr.Operations.Length]; for (int i = 0; i < transactionXdr.Operations.Length; i++) { operations[i] = Operation.FromXdr(transactionXdr.Operations[i]); } Transaction transaction = new Transaction(sourceAccount, fee, sequenceNumber, operations, memo, timeBounds); foreach (var signature in envelope.Signatures) { transaction.Signatures.Add(signature); } return(transaction); }