/// <summary> /// Gets the storage key bytes hash. /// </summary> /// <param name="module">The module.</param> /// <param name="item">The item.</param> /// <returns></returns> public static byte[] GetStorageKeyBytesHash(string module, string item) { var mBytes = Encoding.ASCII.GetBytes(module); var iBytes = Encoding.ASCII.GetBytes(item); return(HashExtension.Twox128(mBytes).Concat(HashExtension.Twox128(iBytes)).ToArray()); }
/// <summary> /// Gets the address from. /// </summary> /// <param name="bytes">The bytes.</param> /// <returns></returns> public static string GetAddressFrom(byte[] bytes) { var SR25519_PUBLIC_SIZE = 32; var PUBLIC_KEY_LENGTH = 32; var plainAddr = Enumerable .Repeat((byte)0x2A, 35) .ToArray(); bytes.CopyTo(plainAddr.AsMemory(1)); var ssPrefixed = new byte[SR25519_PUBLIC_SIZE + 8]; var ssPrefixed1 = new byte[] { 0x53, 0x53, 0x35, 0x38, 0x50, 0x52, 0x45 }; ssPrefixed1.CopyTo(ssPrefixed, 0); plainAddr.AsSpan(0, SR25519_PUBLIC_SIZE + 1).CopyTo(ssPrefixed.AsSpan(7)); var blake2bHashed = HashExtension.Blake2(ssPrefixed, 0, SR25519_PUBLIC_SIZE + 8); plainAddr[1 + PUBLIC_KEY_LENGTH] = blake2bHashed[0]; plainAddr[2 + PUBLIC_KEY_LENGTH] = blake2bHashed[1]; var addrCh = Base58.Bitcoin.Encode(plainAddr).ToArray(); return(new string(addrCh)); }
/// <summary> /// Gets the public key from. /// </summary> /// <param name="address">The address.</param> /// <returns></returns> /// <exception cref="ApplicationException"> /// Address checksum is wrong. /// or /// Address checksum is wrong. /// </exception> public static byte[] GetPublicKeyFrom(string address) { var PUBLIC_KEY_LENGTH = 32; var pubkByteList = new List <byte>(); var bs58decoded = Base58.Bitcoin.Decode(address).ToArray(); var len = bs58decoded.Length; if (len == 35) { byte[] ssPrefixed = { 0x53, 0x53, 0x35, 0x38, 0x50, 0x52, 0x45 }; pubkByteList.AddRange(ssPrefixed); pubkByteList.AddRange(bs58decoded.Take(PUBLIC_KEY_LENGTH + 1)); var blake2bHashed = HashExtension.Blake2(pubkByteList.ToArray(), 512); if (bs58decoded[PUBLIC_KEY_LENGTH + 1] != blake2bHashed[0] || bs58decoded[PUBLIC_KEY_LENGTH + 2] != blake2bHashed[1]) { throw new ApplicationException("Address checksum is wrong."); } return(bs58decoded.Skip(1).Take(PUBLIC_KEY_LENGTH).ToArray()); } throw new ApplicationException("Address checksum is wrong."); }
internal static UnCheckedExtrinsic SubmitExtrinsic(bool signed, Account account, Method method, Era era, uint nonce, uint tip, Hash genesis, Hash startEra) { var uncheckedExtrinsic = new UnCheckedExtrinsic(signed, account, method, era, nonce, tip, genesis, startEra); if (!signed) { return(uncheckedExtrinsic); } var payload = uncheckedExtrinsic.GetPayload().Encode(); /// Payloads longer than 256 bytes are going to be `blake2_256`-hashed. if (payload.Length > 256) { payload = HashExtension.Blake2(payload, 256); } byte[] signature; switch (account.KeyType) { case KeyType.SR25519: signature = Sr25519v091.SignSimple(account.PublicKey, account.PrivateKey, payload); break; case KeyType.ED25519: signature = Ed25519.Sign(payload, account.PrivateKey); break; default: throw new Exception($"Unknown key type found '{account.KeyType}'."); } uncheckedExtrinsic.AddPayloadSignature(signature); return(uncheckedExtrinsic); }
public static string GetStorage(Module module, Item item, byte[] parameter = null) { var mBytes = Encoding.ASCII.GetBytes(module.Name); var iBytes = Encoding.ASCII.GetBytes(item.Name); var keybytes = HashExtension.XXHash128(mBytes).Concat(HashExtension.XXHash128(iBytes)).ToArray(); switch (item.Type) { case Storage.Type.Plain: return(BitConverter.ToString(keybytes).Replace("-", "")); case Storage.Type.Map: switch (item.Function.Hasher) { case Storage.Hasher.Identity: return(BitConverter.ToString(keybytes.Concat(parameter).ToArray()).Replace("-", "")); case Storage.Hasher.Blake2_128: case Storage.Hasher.Blake2_256: case Storage.Hasher.Blake2_128Concat: return(BitConverter.ToString(keybytes.Concat(HashExtension.Blake2Concat(parameter)).ToArray()).Replace("-", "")); case Storage.Hasher.Twox128: case Storage.Hasher.Twox256: case Storage.Hasher.Twox64Concat: case Storage.Hasher.None: default: break; } return(""); case Storage.Type.DoubleMap: return(""); default: return(""); } }
/// <summary> /// Create a request for a storage call. /// </summary> /// <param name="module">The module, is listed in the metadata of the node.</param> /// <param name="item">The item, is listed in the metadata of the node.</param> /// <param name="parameter">The parameter.</param> /// <returns></returns> public static string GetStorage(Module module, Item item, string[] key1Param = null, string[] key2Param = null) { var keybytes = GetStorageKeyBytesHash(module, item); byte[] key1ParamBytes = null; if (item.Function?.Key1 != null) { key1ParamBytes = GetParameterBytes(item.Function.Key1, key1Param); } byte[] key2ParamBytes = null; if (item.Function?.Key2 != null) { key2ParamBytes = GetParameterBytes(item.Function.Key2, key2Param); } // https://www.shawntabrizi.com/substrate/querying-substrate-storage-via-rpc/ byte[] key1Hashed, key2Hashed; switch (item.Type) { // xxhash128("ModuleName") + xxhash128("StorageName") case Storage.Type.Plain: return(Utils.Bytes2HexString(keybytes)); // xxhash128("ModuleName") + xxhash128("StorageName") + blake256hash("StorageItemKey") case Storage.Type.Map: key1Hashed = HashExtension.Hash(item.Function.Hasher, key1ParamBytes); return(Utils.Bytes2HexString(keybytes.Concat(key1Hashed).ToArray())); // xxhash128("ModuleName") + xxhash128("StorageName") + blake256hash("FirstKey") + blake256hash("SecondKey") case Storage.Type.DoubleMap: key1Hashed = HashExtension.Hash(item.Function.Hasher, key1ParamBytes); key2Hashed = HashExtension.Hash(item.Function.Key2Hasher, key2ParamBytes); return(Utils.Bytes2HexString(keybytes.Concat(key1Hashed).Concat(key2Hashed).ToArray())); default: throw new NotSupportedException(); } }