/// <summary> /// Sign the provided message using a Verifiable Random Function (VRF) /// and if the result is less than param threshold provide the proof. /// </summary> /// <param name="message">The raw bytes of the message to sign.</param> /// <param name="keypair">The keypair for signing.</param> /// <param name="threshold">Threshold (byte array, 16 bytes).</param> /// <param name="result">VRF signature output & proof.</param> /// <returns>True if VRF signature was successful (and result below threshold)</returns> public static bool VrfSignIfLess(byte[] message, SR25519Keypair keypair, byte[] threshold, out VrfSignResult result) { result = null; if (threshold?.Length != Constants.SR25519_VRF_THRESHOLD_SIZE) { throw new SR25519VrfException(StringConstants.BadVrfTresholdSizeMessage); } var vrfOutputAndProof = new byte[ Constants.SR25519_VRF_OUTPUT_SIZE + Constants.SR25519_VRF_PROOF_SIZE ]; var rc = Bindings.VrfSignIfLess( vrfOutputAndProof, keypair.GetBytes(), message, Convert.ToUInt64(message.Length), threshold); result = new VrfSignResult(rc, vrfOutputAndProof); return(rc.Result == Sr25519SignatureResult.Ok && rc.IsLess); }
public void Ok() { BigInteger seed = new BigInteger(DateTime.Now.Ticks) << DateTime.Now.Second; var rnd = new Random(BitConverter.ToInt32(seed.ToByteArray().Take(4).ToArray())); var publicKey = new byte[32]; var secretKey = new byte[64]; var payload = new byte[64]; rnd.NextBytes(publicKey); rnd.NextBytes(secretKey); rnd.NextBytes(payload); var pk = AddressUtils.GetPublicKeyFromAddr("5GWYBLjRtCQLXQmcyyRa6KaF1ihuqLjvVDE2gswJsEMxd9Qm"); var kp = new SR25519Keypair(pk.Bytes, secretKey); var sig = SR25519.Sign(payload, (ulong)payload.Length, kp); var arrayNotSame = new Func <byte[], bool>((btArr) => { return(btArr.GroupBy((i) => i).Count() > 50); }); Assert.True(sig.Length == 64); Assert.True(arrayNotSame(sig)); }
/// <summary> /// Get the byte array representation of a SR25519Keypair object. /// </summary> /// <param name="keys">The SR25519Keypair object.</param> /// <returns>Byte array.</returns> public static byte[] GetBytes(this SR25519Keypair keys) { var bytes = new byte[96]; Buffer.BlockCopy(keys.Secret, 0, bytes, 0, Constants.SR25519_SECRET_SIZE); Buffer.BlockCopy(keys.Public, 0, bytes, Constants.SR25519_SECRET_SIZE, Constants.SR25519_PUBLIC_SIZE); return(bytes); }
/// <summary> /// Signs a message and returns the signature. /// </summary> /// <param name="message">The raw bytes of the message to sign.</param> /// <param name="keypair">The keypair for signing.</param> /// <returns>Signature as byte[]</returns> public static byte[] Sign(byte[] message, SR25519Keypair keypair) { var signature = new byte[Constants.SR25519_SIGNATURE_SIZE]; Bindings.Sign( signature, keypair.Public, keypair.Secret, message, Convert.ToUInt64(message.Length)); return(signature); }
/// <summary> /// Signs a message and returns the signature. /// </summary> /// <param name="message">The message to sign.</param> /// <param name="keypair">The keypair for signing.</param> /// <returns>Signature as byte[]</returns> public static byte[] Sign(string message, SR25519Keypair keypair) { var bytes = Encoding.UTF8.GetBytes(message); var signature = new byte[Constants.SR25519_SIGNATURE_SIZE]; Bindings.Sign( signature, keypair.Public, keypair.Secret, bytes, Convert.ToUInt64(bytes.Length)); return(signature); }
/// <summary> /// Soft derive a new keypair from an existing keypair. /// </summary> /// <param name="keypair">Input keypair.</param> /// <param name="chainCodeHex">Chain code as hex string.</param> /// <returns>SR25519Keypair</returns> public static SR25519Keypair SoftDeriveKeypair(SR25519Keypair keypair, string chainCodeHex) { byte[] chainCodeBytes = Utils.HexStringToByteArray(chainCodeHex); if (chainCodeBytes.Length != Constants.SR25519_CHAINCODE_SIZE) { throw new SR25519KeypairException(StringConstants.BadChaincodeSizeMessage); } var bytes = keypair.GetBytes(); var derived = new byte[Constants.SR25519_KEYPAIR_SIZE]; Bindings.DeriveKeypairSoft(derived, bytes, chainCodeBytes); return(new SR25519Keypair(derived)); }
/// <summary> /// Signs a message and returns the signature. /// </summary> /// <param name="message">The message to sign.</param> /// <param name="keypair">The keypair for signing.</param> /// <returns>Signature as byte[]</returns> public static byte[] Sign(byte[] message, ulong messageLen, SR25519Keypair keypair) { var signature = new byte[Constants.SR25519_SIGNATURE_SIZE]; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { Bindings.SignSo( signature, keypair.Public, keypair.Secret, message, messageLen); } if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { Bindings.Sign( signature, keypair.Public, keypair.Secret, message, messageLen); } return(signature); }
private string ExtrinsicQueryString(byte[] encodedMethodBytes, string module, string method, Address sender, string privateKey) { _logger.Info("=== Started Invoking Extrinsic ==="); // Get account Nonce var nonce = GetAccountNonce(sender); var compactNonce = Scale.EncodeCompactInteger(nonce); _logger.Info($"sender nonce: {nonce}"); byte[] mmBuf = new byte[3]; // Module + Method var absoluteIndex = _protocolParams.Metadata.GetModuleIndex(module, false); mmBuf[0] = (byte)_protocolParams.Metadata.GetModuleIndex(module, true); mmBuf[1] = (byte)_protocolParams.Metadata.GetCallMethodIndex(absoluteIndex, method); // Address separator mmBuf[2] = Consts.ADDRESS_SEPARATOR; Extrinsic ce = new Extrinsic(); var completeMessage = new byte[encodedMethodBytes.Length + 3]; mmBuf.CopyTo(completeMessage.AsMemory()); encodedMethodBytes.CopyTo(completeMessage.AsMemory(3)); // memcpy(completeMessage + 3, encodedMethodBytes, encodedMethodBytesSize); ce.Signature.Version = Consts.SIGNATURE_VERSION; var senderPK = _protocolParams.Metadata.GetPublicKeyFromAddr(sender); ce.Signature.SignerPublicKey = senderPK.Bytes; ce.Signature.Nonce = nonce; ce.Signature.Era = ExtrinsicEra.IMMORTAL_ERA; // Format signature payload SignaturePayload sp = new SignaturePayload(); sp.Nonce = nonce; sp.MethodBytesLength = encodedMethodBytes.Length + 3; sp.MethodBytes = completeMessage; sp.Era = ExtrinsicEra.IMMORTAL_ERA; sp.AuthoringBlockHash = _protocolParams.GenesisBlockHash; // Serialize and Sign payload var signaturePayloadBytes = new byte[Consts.MAX_METHOD_BYTES_SZ]; long payloadLength = sp.SerializeBinary(ref signaturePayloadBytes); var secretKeyVec = Converters.StringToByteArray(privateKey); // p/invoke version var kp = new SR25519Keypair(ce.Signature.SignerPublicKey, secretKeyVec); var sig = SR25519.Sign(signaturePayloadBytes, (ulong)payloadLength, kp); ce.Signature.Sr25519Signature = sig; //// adopted version //var sr25519 = new Sr25519(); //var message = signaturePayloadBytes.AsMemory().Slice(0, (int)payloadLength).ToArray(); //var sig2 = sr25519.Sign(secretKeyVec, te.Signature.SignerPublicKey, message); //te.Signature.Sr25519Signature = sig2.ToBytes(); // Copy signature bytes to transaction ce.Signature.Sr25519Signature = sig; var length = Consts.DEFAULT_FIXED_EXSTRINSIC_SIZE + encodedMethodBytes.Length + compactNonce.Length - 1; var compactLength = Scale.EncodeCompactInteger(length); ///////////////////////////////////////// // Serialize message signature and write to buffer long writtenLength = 0; var buf = new byte[2048]; var buf2 = new List <byte>(); // Length writtenLength += Scale.WriteCompactToBuf(compactLength, ref buf, writtenLength); // Signature version buf[writtenLength++] = ce.Signature.Version; // Address separator buf[writtenLength++] = Consts.ADDRESS_SEPARATOR; // Signer public key ce.Signature.SignerPublicKey.CopyTo(buf.AsMemory((int)writtenLength)); writtenLength += Consts.SR25519_PUBLIC_SIZE; // SR25519 Signature ce.Signature.Sr25519Signature.CopyTo(buf.AsMemory((int)writtenLength)); writtenLength += Consts.SR25519_SIGNATURE_SIZE; // Nonce writtenLength += Scale.WriteCompactToBuf(compactNonce, ref buf, writtenLength); // Extrinsic Era buf[writtenLength++] = (byte)ce.Signature.Era; // Serialize and send transaction var teBytes = new byte[Consts.MAX_METHOD_BYTES_SZ]; teBytes = buf; completeMessage.AsMemory().CopyTo(teBytes.AsMemory((int)writtenLength)); long teByteLength = writtenLength + encodedMethodBytes.Length + 3; return($"0x{Converters.ByteArrayToString(teBytes, (int)teByteLength)}"); }
public int SignAndSendTransfer(string sender, string privateKey, string recipient, BigInteger amount, Action <string> callback) { _logger.Info("=== Starting a Transfer Extrinsic ==="); // Get account Nonce var address = new Address { Symbols = sender }; var nonce = GetAccountNonce(address); _logger.Info($"sender nonce: {nonce} "); // Format transaction TransferExtrinsic te = new TransferExtrinsic(); te.Method.ModuleIndex = _protocolParams.BalanceModuleIndex; te.Method.MethodIndex = _protocolParams.TransferMethodIndex; var recipientPK = _protocolParams.Metadata.GetPublicKeyFromAddr(new Address(recipient)); te.Method.ReceiverPublicKey = recipientPK.Bytes; te.Method.Amount = amount; te.Signature.Version = Consts.SIGNATURE_VERSION; var senderPK = _protocolParams.Metadata.GetPublicKeyFromAddr(new Address(sender)); te.Signature.SignerPublicKey = senderPK.Bytes; te.Signature.Nonce = nonce; te.Signature.Era = ExtrinsicEra.IMMORTAL_ERA; // Format signature payload SignaturePayload sp = new SignaturePayload(); sp.Nonce = nonce; var methodBytes = new byte[Consts.MAX_METHOD_BYTES_SZ]; sp.MethodBytesLength = (int)te.SerializeMethodBinary(ref methodBytes); sp.MethodBytes = methodBytes; sp.Era = ExtrinsicEra.IMMORTAL_ERA; sp.AuthoringBlockHash = _protocolParams.GenesisBlockHash; // Serialize and Sign payload var signaturePayloadBytes = new byte[Consts.MAX_METHOD_BYTES_SZ]; long payloadLength = sp.SerializeBinary(ref signaturePayloadBytes); byte[] secretKeyVec = Converters.StringToByteArray(privateKey); // p/invoke version var kp = new SR25519Keypair(te.Signature.SignerPublicKey, secretKeyVec); var sig = SR25519.Sign(signaturePayloadBytes, (ulong)payloadLength, kp); te.Signature.Sr25519Signature = sig; //// adopted version //var sr25519 = new Sr25519(); //var message = signaturePayloadBytes.AsMemory().Slice(0, (int)payloadLength).ToArray(); //var sig2 = sr25519.Sign(secretKeyVec, te.Signature.SignerPublicKey, message); //te.Signature.Sr25519Signature = sig2.ToBytes(); // Serialize and send transaction var teBytes = new byte[Consts.MAX_METHOD_BYTES_SZ]; long teByteLength = te.SerializeBinary(ref teBytes); string teStr = $"0x{Converters.ByteArrayToString(teBytes, (int)teByteLength)}"; var query = new JObject { { "method", "author_submitAndWatchExtrinsic" }, { "params", new JArray { teStr } } }; // Send == Subscribe callback to completion return(Subscribe(query, (json) => { callback(json.ToString()); })); }