Skip to content

Commit 023e107

Browse files
authored
Merge pull request #478 from kingsznhone/master
Added Address lookup table Instruction & removed bouncy castle + deprecated code cleanup
2 parents 1e0981a + 80979ad commit 023e107

13 files changed

+316
-138
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
using System.Collections.Generic;
2+
using Solnet.Rpc.Models;
3+
using Solnet.Wallet;
4+
5+
namespace Solnet.Programs
6+
{
7+
public static class AddressLookupTableProgram
8+
{
9+
/// <summary>
10+
/// The public key of the ATL Program.
11+
/// </summary>
12+
public static readonly PublicKey ProgramIdKey = new("AddressLookupTab1e1111111111111111111111111");
13+
14+
/// <summary>
15+
/// The program's name.
16+
/// </summary>
17+
private const string ProgramName = "Address Lookup Table Program";
18+
19+
/// <summary>
20+
/// Create New Address Lookup Table Instruction
21+
/// </summary>
22+
/// <param name="Authority"></param>
23+
/// <param name="Payer"></param>
24+
/// <param name="RecentSlot"></param>
25+
/// <returns></returns>
26+
public static TransactionInstruction CreateAddressLookupTable(
27+
PublicKey Authority, PublicKey Payer, PublicKey ALT,byte bump, ulong RecentSlot)
28+
{
29+
//byte[] recentSlotBytes = BitConverter.GetBytes(RecentSlot);
30+
//byte[] seed = Authority.KeyBytes.Concat(recentSlotBytes).ToArray();
31+
//PublicKey.TryFindProgramAddress(new List<byte[]> { seed }, ProgramIdKey, out PublicKey ALTaddress, out byte bump);
32+
33+
List<AccountMeta> keys = new()
34+
{
35+
AccountMeta.Writable(ALT, false),
36+
AccountMeta.ReadOnly(Authority, false),
37+
AccountMeta.Writable(Payer, true),
38+
AccountMeta.ReadOnly(SystemProgram.ProgramIdKey, false)
39+
};
40+
return new TransactionInstruction
41+
{
42+
ProgramId = ProgramIdKey.KeyBytes,
43+
Keys = keys,
44+
Data = AddressLookupTableProgramData.EncodeCreateAddressLookupTableData(RecentSlot, bump)
45+
};
46+
}
47+
48+
/// <summary>
49+
/// Freeze Lookup Table Instruction
50+
/// </summary>
51+
/// <param name="LookupTable"></param>
52+
/// <param name="Authority"></param>
53+
/// <returns></returns>
54+
public static TransactionInstruction FreezeLookupTable(PublicKey LookupTable, PublicKey Authority)
55+
{
56+
List<AccountMeta> keys = new()
57+
{
58+
AccountMeta.Writable(LookupTable, false),
59+
AccountMeta.ReadOnly(Authority, true)
60+
};
61+
return new TransactionInstruction
62+
{
63+
ProgramId = ProgramIdKey.KeyBytes,
64+
Keys = keys,
65+
Data = AddressLookupTableProgramData.EncodeFreezeLookupTableData()
66+
};
67+
}
68+
69+
/// <summary>
70+
/// Extend Lookup Table Instruction
71+
/// </summary>
72+
/// <param name="LookupTable"></param>
73+
/// <param name="Authority"></param>
74+
/// <param name="Payer"></param>
75+
/// <param name="keys"></param>
76+
/// <returns></returns>
77+
public static TransactionInstruction ExtendLookupTable(PublicKey LookupTable, PublicKey Authority, PublicKey Payer, List<PublicKey> keys)
78+
{
79+
List<AccountMeta> meta = new()
80+
{
81+
AccountMeta.Writable(LookupTable, false),
82+
AccountMeta.ReadOnly(Authority, true),
83+
AccountMeta.Writable(Payer, true),
84+
AccountMeta.ReadOnly(SystemProgram.ProgramIdKey, false)
85+
};
86+
return new TransactionInstruction
87+
{
88+
ProgramId = ProgramIdKey.KeyBytes,
89+
Keys = meta,
90+
Data = AddressLookupTableProgramData.EncodeExtendLookupTableData((ulong)keys.Count, keys)
91+
};
92+
}
93+
94+
/// <summary>
95+
/// Deactivate Lookup Table Instruction
96+
/// </summary>
97+
/// <param name="LookupTable"></param>
98+
/// <param name="Authority"></param>
99+
/// <returns></returns>
100+
public static TransactionInstruction DeactivateLookupTable(PublicKey LookupTable, PublicKey Authority)
101+
{
102+
List<AccountMeta> keys = new()
103+
{
104+
AccountMeta.Writable(LookupTable, false),
105+
AccountMeta.ReadOnly(Authority, true)
106+
};
107+
return new TransactionInstruction
108+
{
109+
ProgramId = ProgramIdKey.KeyBytes,
110+
Keys = keys,
111+
Data = AddressLookupTableProgramData.EncodeDeactivateLookupTableData()
112+
};
113+
}
114+
115+
/// <summary>
116+
/// Close Lookup Table Instruction
117+
/// </summary>
118+
/// <param name="LookupTable"></param>
119+
/// <param name="Authority"></param>
120+
/// <param name="Recipient"></param>
121+
/// <returns></returns>
122+
public static TransactionInstruction CloseLookupTable(PublicKey LookupTable, PublicKey Authority, PublicKey Recipient)
123+
{
124+
List<AccountMeta> keys = new()
125+
{
126+
AccountMeta.Writable(LookupTable, false),
127+
AccountMeta.ReadOnly(Authority, true),
128+
AccountMeta.Writable(Recipient, false)
129+
};
130+
return new TransactionInstruction
131+
{
132+
ProgramId = ProgramIdKey.KeyBytes,
133+
Keys = keys,
134+
Data = AddressLookupTableProgramData.EncodeCloseLookupTableData()
135+
};
136+
}
137+
138+
139+
}
140+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using System.Collections.Generic;
2+
using Solnet.Programs.Utilities;
3+
using Solnet.Wallet;
4+
5+
namespace Solnet.Programs
6+
{
7+
internal static class AddressLookupTableProgramData
8+
{
9+
internal const int MethodOffset = 0;
10+
11+
/// <summary>
12+
/// Encode transaction instruction data for the <see cref="AddressLookupTableProgramInstruction.Values.CreateLookupTable"/> method.
13+
/// </summary>
14+
/// <param name="Authority">Who own this table </param>
15+
/// <param name="Payer">Who pay for this table</param>
16+
/// <param name="RecentSlot">For random seed</param>
17+
/// <returns></returns>
18+
internal static byte[] EncodeCreateAddressLookupTableData( ulong RecentSlot,byte bump)
19+
{
20+
byte[] data = new byte[13];
21+
data.WriteU32((uint)AddressLookupTableProgramInstruction.Values.CreateLookupTable, MethodOffset);
22+
data.WriteU64(RecentSlot, 4);
23+
data.WriteU8(bump, 12);
24+
25+
return data;
26+
}
27+
28+
/// <summary>
29+
/// Encode transaction instruction data for the <see cref="AddressLookupTableProgramInstruction.Values.FreezeLookupTable"/> method.
30+
/// </summary>
31+
/// <returns></returns>
32+
internal static byte[] EncodeFreezeLookupTableData()
33+
{
34+
byte[] data = new byte[4];
35+
data.WriteU32((uint)AddressLookupTableProgramInstruction.Values.FreezeLookupTable, MethodOffset);
36+
return data;
37+
}
38+
39+
/// <summary>
40+
/// Encode transaction instruction data for the <see cref="AddressLookupTableProgramInstruction.Values.ExtendLookupTable"/> method.
41+
/// </summary>
42+
/// <param name="RecentSlot"></param>
43+
/// <param name="Keys"></param>
44+
/// <returns></returns>
45+
internal static byte[] EncodeExtendLookupTableData(ulong KeyCounts,List<PublicKey> Keys)
46+
{
47+
byte[] data = new byte[12 + Keys.Count * 32];
48+
data.WriteU32((uint)AddressLookupTableProgramInstruction.Values.ExtendLookupTable, MethodOffset);
49+
data.WriteU64(KeyCounts, 4);
50+
for (int i = 0; i < Keys.Count; i++)
51+
{
52+
data.WritePubKey(Keys[i], 12 + i * 32);
53+
}
54+
return data;
55+
}
56+
57+
/// <summary>
58+
/// Encode transaction instruction data for the <see cref="AddressLookupTableProgramInstruction.Values.DeactivateLookupTable"/> method.
59+
/// </summary>
60+
/// <returns></returns>
61+
internal static byte[] EncodeDeactivateLookupTableData()
62+
{
63+
byte[] data = new byte[4];
64+
data.WriteU32((uint)AddressLookupTableProgramInstruction.Values.DeactivateLookupTable, MethodOffset);
65+
return data;
66+
}
67+
68+
/// <summary>
69+
/// Encode transaction instruction data for the <see cref="AddressLookupTableProgramInstruction.Values.CloseLookupTable"/> method.
70+
/// </summary>
71+
/// <returns></returns>
72+
internal static byte[] EncodeCloseLookupTableData()
73+
{
74+
byte[] data = new byte[4];
75+
data.WriteU32((uint)AddressLookupTableProgramInstruction.Values.CloseLookupTable, MethodOffset);
76+
return data;
77+
}
78+
}
79+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System.Collections.Generic;
2+
3+
namespace Solnet.Programs
4+
{
5+
internal static class AddressLookupTableProgramInstruction
6+
{
7+
/// <summary>
8+
/// Represents the user-friendly names for the instruction types for the <see cref="AddressLookupTableProgram"/>.
9+
/// </summary>
10+
internal static readonly Dictionary<Values, string> Names = new()
11+
{
12+
{ Values.CreateLookupTable, "Create Lookup Table" },
13+
{ Values.FreezeLookupTable, "Freeze Lookup Table" },
14+
{ Values.ExtendLookupTable, "Extend Lookup Table" },
15+
{ Values.DeactivateLookupTable, "Deactivate Lookup Table" },
16+
{ Values.CloseLookupTable, "Close Lookup Table" }
17+
};
18+
19+
/// <summary>
20+
/// Represents the instruction types for the <see cref="AddressLookupTableProgram"/>.
21+
/// </summary>
22+
internal enum Values : byte
23+
{
24+
CreateLookupTable = 0,
25+
FreezeLookupTable = 1,
26+
ExtendLookupTable = 2,
27+
DeactivateLookupTable =3,
28+
CloseLookupTable =4
29+
}
30+
}
31+
}

src/Solnet.Rpc/Solnet.Rpc.csproj

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
1111
<_Parameter1>Solnet.Rpc.Test</_Parameter1>
1212
</AssemblyAttribute>
13-
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
14-
<_Parameter1>Solnet.Extensions.Test</_Parameter1>
15-
</AssemblyAttribute>
16-
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
13+
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
14+
<_Parameter1>Solnet.Extensions.Test</_Parameter1>
15+
</AssemblyAttribute>
16+
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
1717
<_Parameter1>DynamicProxyGenAssembly2</_Parameter1>
1818
</AssemblyAttribute>
1919
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.0" />

src/Solnet.Wallet/Account.cs

+26-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using Bifrost.Security;
22
using Solnet.Wallet.Utilities;
33
using System;
4+
using System.Collections.Generic;
45
using System.Diagnostics;
6+
using System.Security.Principal;
57

68
namespace Solnet.Wallet
79
{
@@ -27,9 +29,8 @@ public class Account
2729
public Account()
2830
{
2931
byte[] seed = GenerateRandomSeed();
30-
31-
(byte[] privateKey, byte[] publicKey) = Utils.EdKeyPairFromSeed(seed);
32-
32+
byte[] privateKey = Ed25519.ExpandedPrivateKeyFromSeed(seed);
33+
byte[] publicKey = Ed25519.PublicKeyFromSeed(seed);
3334
PrivateKey = new PrivateKey(privateKey);
3435
PublicKey = new PublicKey(publicKey);
3536
}
@@ -64,7 +65,7 @@ public static Account FromSecretKey(string secretKey)
6465
throw new ArgumentException("Not a secret key");
6566
}
6667

67-
Account acc = new Account(skeyBytes, skeyBytes.Slice(32, 64));
68+
Account acc = new Account(skeyBytes, skeyBytes.AsSpan(32, 32).ToArray());
6869

6970
return acc;
7071
}
@@ -121,5 +122,25 @@ public override bool Equals(object obj)
121122

122123
/// <inheritdoc cref="GetHashCode"/>
123124
public override int GetHashCode() => PublicKey.GetHashCode();
125+
126+
public static List<Account> ImportMany(List<string> Keys)
127+
{
128+
List<Account> accounts = new List<Account>();
129+
foreach (string key in Keys)
130+
{
131+
accounts.Add(FromSecretKey(key));
132+
}
133+
return accounts;
134+
}
135+
136+
public static List<Account> ImportMany(List<byte[]> Keys)
137+
{
138+
List<Account> accounts = new List<Account>();
139+
foreach (byte[] key in Keys)
140+
{
141+
accounts.Add(new Account(key, key.AsSpan(32, 32).ToArray()));
142+
}
143+
return accounts;
144+
}
124145
}
125-
}
146+
}

src/Solnet.Wallet/Bip39/HardcodedWordListSource.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ static HardcodedWordlistSource()
6868
/// <returns>A task which returns the word list.</returns>
6969
public Task<WordList> LoadAsync(string name)
7070
{
71-
string list = WordLists.TryGet(name);
71+
WordLists.TryGetValue(name,out string list);
7272
if (list == null)
7373
return null;
7474
return Task.FromResult(new WordList(list.Split(new[] { "\n" }, StringSplitOptions.RemoveEmptyEntries),
@@ -78,4 +78,4 @@ public Task<WordList> LoadAsync(string name)
7878

7979
#endregion
8080
}
81-
}
81+
}

src/Solnet.Wallet/Bip39/Mnemonic.cs

+3-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
using Org.BouncyCastle.Crypto.Digests;
2-
using Org.BouncyCastle.Crypto.Generators;
3-
using Org.BouncyCastle.Crypto.Parameters;
41
using Solnet.Wallet.Utilities;
52
using System;
63
using System.Collections;
@@ -63,7 +60,7 @@ private Mnemonic(WordList wordList, byte[] entropy = null)
6360
throw new ArgumentException("The length for entropy should be " + string.Join(",", EntArray) + " bits", nameof(entropy));
6461

6562
int cs = CsArray[i];
66-
byte[] checksum = Utils.Sha256(entropy);
63+
byte[] checksum = SHA256.HashData(entropy);
6764
BitWriter entropyResult = new();
6865

6966
entropyResult.Write(entropy);
@@ -135,7 +132,7 @@ public bool IsValidChecksum
135132
BitArray bits = WordList.ToBits(Indices);
136133
writer.Write(bits, ent);
137134
byte[] entropy = writer.ToBytes();
138-
byte[] checksum = Utils.Sha256(entropy);
135+
byte[] checksum = SHA256.HashData(entropy);
139136

140137
writer.Write(checksum, cs);
141138
int[] expectedIndices = writer.ToIntegers();
@@ -286,4 +283,4 @@ public override string ToString()
286283
return _mnemonic;
287284
}
288285
}
289-
}
286+
}

src/Solnet.Wallet/Bip39/WordList.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ private static async Task<WordList> LoadWordList(string name)
166166
if (result != null)
167167
lock (LoadedLists)
168168
{
169-
LoadedLists.AddOrReplace(name, result);
169+
LoadedLists[name] = result;
170170
}
171171

172172
return result;
@@ -429,4 +429,4 @@ public static BitArray ToBits(int[] values)
429429
return result;
430430
}
431431
}
432-
}
432+
}

0 commit comments

Comments
 (0)