示例#1
0
        /// <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);
        }
示例#4
0
        /// <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);
        }
示例#5
0
        /// <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);
        }
示例#6
0
        /// <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());
            }));
        }