diff --git a/stellar-dotnet-sdk-test/FeeBumpTransactionTest.cs b/stellar-dotnet-sdk-test/FeeBumpTransactionTest.cs index fd240998..5a271ebe 100644 --- a/stellar-dotnet-sdk-test/FeeBumpTransactionTest.cs +++ b/stellar-dotnet-sdk-test/FeeBumpTransactionTest.cs @@ -145,28 +145,21 @@ public void TestTransactionHash() var network = Network.Test(); var innerTx = CreateInnerTransaction(100, network); - Assert.AreEqual( - "95dcf35a43a1a05bcd50f3eb148b31127829a9460dc32a17c4a7f7c4677409d4", - Util.BytesToHex(innerTx.Hash(network)).ToLowerInvariant()); + Assert.AreEqual("2a8ead3351faa7797b284f59027355ddd69c21adb8e4da0b9bb95531f7f32681", Util.BytesToHex(innerTx.Hash(network)).ToLowerInvariant()); var feeSource = KeyPair.FromAccountId("GDQNY3PBOJOKYZSRMK2S7LHHGWZIUISD4QORETLMXEWXBI7KFZZMKTL3"); var feeBumpTx = TransactionBuilder.BuildFeeBumpTransaction(feeSource, innerTx, 200); - Assert.AreEqual( - "382b1588ee8b315177a34ae96ebcaeb81c0ad3e04fee7c6b5a583b826517e1e4", - Util.BytesToHex(feeBumpTx.Hash(network)).ToLowerInvariant()); + Assert.AreEqual("58266712c0c1d1cd98faa0e0159605a361cf2a5ca44ad69650eeb1d27ee62334", Util.BytesToHex(feeBumpTx.Hash(network)).ToLowerInvariant()); } private Transaction CreateInnerTransaction(uint fee, Network network) { var source = KeyPair.FromSecretSeed("SCH27VUZZ6UAKB67BDNF6FA42YMBMQCBKXWGMFD5TZ6S5ZZCZFLRXKHS"); - var destination = - MuxedAccountMed25519.FromMuxedAccountId( - "MCAAAAAAAAAAAAB7BQ2L7E5NBWMXDUCMZSIPOBKRDSBYVLMXGSSKF6YNPIB7Y77ITKNOG"); + var destination = KeyPair.FromAccountId("GA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVSGZ"); var account = new Account(source, 2908908335136768L); var innerTx = new TransactionBuilder(account) - .AddOperation( - new PaymentOperation.Builder(destination, new AssetTypeNative(), "200.0").Build()) + .AddOperation(new PaymentOperation.Builder(destination, new AssetTypeNative(), "200.0").Build()) .SetFee(fee) .AddTimeBounds(new TimeBounds(10, 11)) .Build(); diff --git a/stellar-dotnet-sdk-test/MuxedAccountTest.cs b/stellar-dotnet-sdk-test/MuxedAccountTest.cs index 210ab089..e9e6eff7 100644 --- a/stellar-dotnet-sdk-test/MuxedAccountTest.cs +++ b/stellar-dotnet-sdk-test/MuxedAccountTest.cs @@ -9,11 +9,10 @@ public class MuxedAccountTest [TestMethod] public void TestFromAccountId() { - var muxed = MuxedAccountMed25519.FromMuxedAccountId( - "MAAAAAAAAAAAJURAAB2X52XFQP6FBXLGT6LWOOWMEXWHEWBDVRZ7V5WH34Y22MPFBHUHY"); + var muxed = MuxedAccountMed25519.FromMuxedAccountId("MAQAA5L65LSYH7CQ3VTJ7F3HHLGCL3DSLAR2Y47263D56MNNGHSQSAAAAAAAAAAE2LP26"); Assert.AreEqual(1234UL, muxed.Id); Assert.AreEqual("GAQAA5L65LSYH7CQ3VTJ7F3HHLGCL3DSLAR2Y47263D56MNNGHSQSTVY", muxed.Key.Address); - Assert.AreEqual("MAAAAAAAAAAAJURAAB2X52XFQP6FBXLGT6LWOOWMEXWHEWBDVRZ7V5WH34Y22MPFBHUHY", muxed.Address); + Assert.AreEqual("MAQAA5L65LSYH7CQ3VTJ7F3HHLGCL3DSLAR2Y47263D56MNNGHSQSAAAAAAAAAAE2LP26", muxed.Address); } } } \ No newline at end of file diff --git a/stellar-dotnet-sdk-test/StrKeyTest.cs b/stellar-dotnet-sdk-test/StrKeyTest.cs index 43b0c231..6799f9c0 100644 --- a/stellar-dotnet-sdk-test/StrKeyTest.cs +++ b/stellar-dotnet-sdk-test/StrKeyTest.cs @@ -2,6 +2,7 @@ using stellar_dotnet_sdk; using System.Collections.Generic; using System.Linq; +using xdrSDK = stellar_dotnet_sdk.xdr; namespace stellar_dotnet_sdk_test { @@ -37,25 +38,26 @@ public void TestDecodeInvalidSeed() [TestMethod] public void TestDecodeEncodeMuxedAccount() { - var address = "MAAAAAAAAAAAAAB7BQ2L7E5NBWMXDUCMZSIPOBKRDSBYVLMXGSSKF6YNPIB7Y77ITLVL6"; - var (id, key) = StrKey.DecodeStellarMuxedAccount(address); + var address = "MA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUAAAAAAAAAAAACJUQ"; + var muxed = StrKey.DecodeStellarMuxedAccount(address); Assert.IsTrue(StrKey.IsValidMuxedAccount(address)); - Assert.AreEqual(0UL, id); - var encodedKey = StrKey.EncodeStellarAccountId(key); + Assert.AreEqual(0UL, muxed.Med25519.Id.InnerValue); + + var encodedKey = StrKey.EncodeStellarAccountId(muxed.Med25519.Ed25519.InnerValue); Assert.AreEqual("GA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVSGZ", encodedKey); - Assert.AreEqual(address, StrKey.EncodeStellarMuxedAccount(key, id)); + Assert.AreEqual(address, StrKey.EncodeStellarMuxedAccount(new MuxedAccountMed25519(KeyPair.FromPublicKey(muxed.Med25519.Ed25519.InnerValue), muxed.Med25519.Id.InnerValue).MuxedAccount)); } [TestMethod] public void TestDecodeEncodeMuxedAccountWithLargeId() { - var address = "MCAAAAAAAAAAAAB7BQ2L7E5NBWMXDUCMZSIPOBKRDSBYVLMXGSSKF6YNPIB7Y77ITKNOG"; - var (id, key) = StrKey.DecodeStellarMuxedAccount(address); + var address = "MA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVAAAAAAAAAAAAAJLK"; + var muxed = StrKey.DecodeStellarMuxedAccount(address); Assert.IsTrue(StrKey.IsValidMuxedAccount(address)); - Assert.AreEqual(9223372036854775808UL, id); - var encodedKey = StrKey.EncodeStellarAccountId(key); + Assert.AreEqual(9223372036854775808UL, muxed.Med25519.Id.InnerValue); + var encodedKey = StrKey.EncodeStellarAccountId(muxed.Med25519.Ed25519.InnerValue); Assert.AreEqual("GA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVSGZ", encodedKey); - Assert.AreEqual(address, StrKey.EncodeStellarMuxedAccount(key, id)); + Assert.AreEqual(address, StrKey.EncodeStellarMuxedAccount(new MuxedAccountMed25519(KeyPair.FromPublicKey(muxed.Med25519.Ed25519.InnerValue), muxed.Med25519.Id.InnerValue).MuxedAccount)); } [TestMethod] diff --git a/stellar-dotnet-sdk/MuxedAccountMed25519.cs b/stellar-dotnet-sdk/MuxedAccountMed25519.cs index f323f32c..e2dd5a65 100644 --- a/stellar-dotnet-sdk/MuxedAccountMed25519.cs +++ b/stellar-dotnet-sdk/MuxedAccountMed25519.cs @@ -40,9 +40,9 @@ public static MuxedAccountMed25519 FromMuxedAccountXdr(xdr.MuxedAccount.MuxedAcc /// public static MuxedAccountMed25519 FromMuxedAccountId(string muxedAccountId) { - var (id, data) = StrKey.DecodeStellarMuxedAccount(muxedAccountId); - var key = KeyPair.FromPublicKey(data); - return new MuxedAccountMed25519(key, id); + var muxedAccount = StrKey.DecodeStellarMuxedAccount(muxedAccountId); + var key = KeyPair.FromPublicKey(muxedAccount.Med25519.Ed25519.InnerValue); + return new MuxedAccountMed25519(key, muxedAccount.Med25519.Id.InnerValue); } /// @@ -67,7 +67,7 @@ public xdr.MuxedAccount MuxedAccount /// /// Get the MuxedAccount address, starting with M. /// - public string Address => StrKey.EncodeStellarMuxedAccount(Key.PublicKey, Id); + public string Address => StrKey.EncodeStellarMuxedAccount(MuxedAccount); /// /// Get the MuxedAccount account id, starting with M. diff --git a/stellar-dotnet-sdk/StrKey.cs b/stellar-dotnet-sdk/StrKey.cs index bac288f8..d260ee00 100644 --- a/stellar-dotnet-sdk/StrKey.cs +++ b/stellar-dotnet-sdk/StrKey.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; -using xdr = stellar_dotnet_sdk.xdr; +using xdrSDK = stellar_dotnet_sdk.xdr; namespace stellar_dotnet_sdk { @@ -41,19 +41,20 @@ public static string EncodeSignedPayload(SignedPayloadSigner signedPayloadSigner } } - public static string EncodeStellarMuxedAccount(byte[] data, ulong id) + public static string EncodeStellarMuxedAccount(xdrSDK.MuxedAccount muxedAccount) { - // 8 bytes for 64 bit id + data - var dataToEncode = new byte[8 + data.Length]; - // Prepend the id in network byte order to the data - var idBytes = BitConverter.GetBytes(id); - if (BitConverter.IsLittleEndian) + switch (muxedAccount.Discriminant.InnerValue) { - Array.Reverse(idBytes); + case xdrSDK.CryptoKeyType.CryptoKeyTypeEnum.KEY_TYPE_MUXED_ED25519: + var bytes = muxedAccount.Med25519.Ed25519.InnerValue.Concat(Util.ToByteArray(muxedAccount.Med25519.Id.InnerValue)).ToArray(); + return EncodeCheck(VersionByte.MUXED_ACCOUNT, bytes); + + case xdrSDK.CryptoKeyType.CryptoKeyTypeEnum.KEY_TYPE_ED25519: + return EncodeCheck(VersionByte.ACCOUNT_ID, muxedAccount.Ed25519.InnerValue); + + default: + throw new ArgumentException("invalid discriminant"); } - Buffer.BlockCopy(idBytes, 0, dataToEncode, 0, 8); - Buffer.BlockCopy(data, 0, dataToEncode, 8, data.Length); - return EncodeCheck(VersionByte.MUXED_ACCOUNT, dataToEncode); } public static string EncodeStellarSecretSeed(byte[] data) @@ -82,24 +83,50 @@ public static SignedPayloadSigner DecodeSignedPayload(string data) } } - public static (ulong, byte[]) DecodeStellarMuxedAccount(string data) + public static xdrSDK.MuxedAccount DecodeStellarMuxedAccount(string data) { - var bytes = DecodeCheck(VersionByte.MUXED_ACCOUNT, data); - var keyData = new byte[bytes.Length - 8]; - ulong id; - Buffer.BlockCopy(bytes, 8, keyData, 0, keyData.Length); + xdrSDK.MuxedAccount muxed = new xdrSDK.MuxedAccount(); - if (BitConverter.IsLittleEndian) + if (data.Length == 0) { - var idBuffer = new byte[8]; - Buffer.BlockCopy(bytes, 0, idBuffer, 0, 8); - Array.Reverse(idBuffer); - id = BitConverter.ToUInt64(idBuffer, 0); - return (id, keyData); + throw new ArgumentException("Address is empty"); } - id = BitConverter.ToUInt64(bytes, 0); - return (id, keyData); + switch (DecodeVersionByte(data)) + { + case VersionByte.ACCOUNT_ID: + muxed.Discriminant.InnerValue = xdrSDK.CryptoKeyType.CryptoKeyTypeEnum.KEY_TYPE_ED25519; + + try + { + muxed.Ed25519 = xdrSDK.Uint256.Decode(new xdrSDK.XdrDataInputStream(DecodeStellarAccountId(data))); + } + catch (InvalidOperationException e) + { + throw new ArgumentException("invalid address: " + data, e); + } + break; + + case VersionByte.MUXED_ACCOUNT: + xdrSDK.XdrDataInputStream input = new xdrSDK.XdrDataInputStream(DecodeCheck(VersionByte.MUXED_ACCOUNT, data)); + muxed.Discriminant.InnerValue = xdrSDK.CryptoKeyType.CryptoKeyTypeEnum.KEY_TYPE_MUXED_ED25519; + xdrSDK.MuxedAccount.MuxedAccountMed25519 med = new xdrSDK.MuxedAccount.MuxedAccountMed25519(); + + try + { + med.Ed25519 = xdrSDK.Uint256.Decode(input); + med.Id = xdrSDK.Uint64.Decode(input); + } + catch (InvalidOperationException e) + { + throw new ArgumentException("invalid address: " + data, e); + } + muxed.Med25519 = med; + break; + default: + throw new FormatException("Version byte is invalid"); + } + return muxed; } public static byte[] DecodeStellarSecretSeed(string data) diff --git a/stellar-dotnet-sdk/Util.cs b/stellar-dotnet-sdk/Util.cs index d04dd6b9..b53790cd 100644 --- a/stellar-dotnet-sdk/Util.cs +++ b/stellar-dotnet-sdk/Util.cs @@ -94,6 +94,18 @@ public static void Fill(this T[] arr, T value) arr[i] = value; } + public static byte[] ToByteArray(ulong value) + { + + byte[] result = new byte[8]; + for (int i = 7; i >= 0; i--) + { + result[i] = (byte)(value & 0xffL); + value >>= 8; + } + return result; + } + public static int ComputeByteArrayHash(params byte[] data) { unchecked