Skip to content

Commit cf834bb

Browse files
committed
V4.0.1
Fix schnorr vrf verification.
1 parent 5e36e6a commit cf834bb

7 files changed

Lines changed: 68 additions & 16 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 4.0.1
2+
3+
- Fix schnorr vrf verification.
4+
15
## 4.0.0
26

37
- Minimum required Dart SDK version updated to 3.3.

lib/crypto/crypto/schnorrkel/keys/keys.dart

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -606,10 +606,7 @@ class SchnorrkelSecretKey {
606606
{GenerateRandom? nonceGenerator,
607607
bool kusamaVRF = true,
608608
MerlinTranscript? verifyScript}) {
609-
final publicHashPoint = publicKey().vrfHash(script);
610-
final keyBig = BigintUtils.fromBytes(key(), byteOrder: Endian.little);
611-
final mul = publicHashPoint * keyBig;
612-
final vrf = VRFInOut._(publicHashPoint.toBytes(), mul.toBytes());
609+
final vrf = vrfInOut(script);
613610
return Tuple(
614611
vrf,
615612
dleqProve(vrf,
@@ -618,6 +615,19 @@ class SchnorrkelSecretKey {
618615
verifyScript: verifyScript));
619616
}
620617

618+
/// This function computes the VRF (Verifiable Random Function) input and output
619+
/// using the provided `MerlinTranscript` as the cryptographic context.
620+
///
621+
/// The process involves hashing a transcript with the public key to generate
622+
/// a curve point, multiplying this point with the private key, and returning
623+
/// the corresponding VRF input and output.
624+
VRFInOut vrfInOut(MerlinTranscript script) {
625+
final publicHashPoint = publicKey().vrfHash(script);
626+
final keyBig = BigintUtils.fromBytes(key(), byteOrder: Endian.little);
627+
final mul = publicHashPoint * keyBig;
628+
return VRFInOut._(publicHashPoint.toBytes(), mul.toBytes());
629+
}
630+
621631
/// Generates a Discrete Logarithm Equality Proof (DLEQ) for a Verifiable Random Function (VRF) output.
622632
///
623633
/// This method generates a DLEQ proof for a given VRF output, ensuring the equality of discrete logarithms of

lib/layout/utils/utils.dart

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,26 @@ class LayoutSerializationUtils {
1616
return const SubstrateScaleCUintEncoder().encode(value.toString());
1717
}
1818

19-
static Tuple<int, BigInt> decodeLength(List<int> bytes, {bool sign = false}) {
20-
switch (bytes[0] & 0x03) {
19+
static Tuple<int, BigInt> decodeLength(List<int> bytes,
20+
{bool sign = false, int offset = 0}) {
21+
final byte = bytes[offset];
22+
23+
switch (byte & 0x03) {
2124
case 0x00:
22-
return Tuple(1, BigInt.from(bytes[0]) >> 2);
25+
return Tuple(1, BigInt.from(byte) >> 2);
2326
case 0x01:
24-
final val = BigintUtils.fromBytes(bytes.sublist(0, 2),
27+
final val = BigintUtils.fromBytes(bytes.sublist(offset, offset + 2),
2528
sign: sign, byteOrder: Endian.little);
2629
return Tuple(2, val >> 2);
2730
case 0x02:
28-
final val = BigintUtils.fromBytes(bytes.sublist(0, 4),
31+
final val = BigintUtils.fromBytes(bytes.sublist(offset, offset + 4),
2932
sign: sign, byteOrder: Endian.little);
3033
return Tuple(4, val >> 2);
3134
default:
32-
final int offset = (bytes[0] >> 2) + 5;
33-
final val = BigintUtils.fromBytes(bytes.sublist(1, offset),
35+
final int o = (byte >> 2) + 5;
36+
final val = BigintUtils.fromBytes(bytes.sublist(offset + 1, offset + o),
3437
sign: sign, byteOrder: Endian.little);
35-
return Tuple(offset, val);
38+
return Tuple(o, val);
3639
}
3740
}
3841

lib/signer/substrate/core/verifier.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@ abstract class BaseSubstrateVerifier {
2525
}
2626
}
2727
factory BaseSubstrateVerifier.fromSubstrate(Substrate substrate) {
28+
final publicKey = substrate.publicKey.compressed;
2829
switch (substrate.coinConf.type) {
2930
case EllipticCurveTypes.ed25519:
30-
return SubstrateED25519Verifier.fromKeyBytes(substrate.priveKey.raw);
31+
return SubstrateED25519Verifier.fromKeyBytes(publicKey);
3132
case EllipticCurveTypes.secp256k1:
32-
return SubstrateEcdsaVerifier.fromKeyBytes(substrate.priveKey.raw);
33+
return SubstrateEcdsaVerifier.fromKeyBytes(publicKey);
3334
default:
34-
return SubstrateSr25519Verifier.fromKeyBytes(substrate.priveKey.raw);
35+
return SubstrateSr25519Verifier.fromKeyBytes(publicKey);
3536
}
3637
}
3738
}

lib/signer/substrate/signers/substrate_sr25519.dart

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,32 @@ class SubstrateSr25519Signer implements BaseSubstrateSigner {
8888
}
8989
return vrfResult;
9090
}
91+
92+
bool vrfVerify(List<int> message, List<int> vrfSign,
93+
{List<int>? context, List<int>? extra}) {
94+
if (vrfSign.length != _SubstrateSr25519SignerConst.vrfResultLength &&
95+
vrfSign.length != SchnorrkelKeyCost.vrfProofLength) {
96+
throw ArgumentException(
97+
"Invalid VrfSign bytes length. excepted: ${_SubstrateSr25519SignerConst.vrfResultLength}, ${SchnorrkelKeyCost.vrfProofLength} got: ${vrfSign.length} ");
98+
}
99+
final MerlinTranscript script =
100+
_SubstrateSr25519SignerUtils.substrateVrfSignScript(message, context);
101+
VRFPreOut output;
102+
VRFProof proof;
103+
if (vrfSign.length == SchnorrkelKeyCost.vrfProofLength) {
104+
output = _signer.vrfInOut(script).toVRFPreOut();
105+
proof = VRFProof.fromBytes(vrfSign);
106+
} else {
107+
output = VRFPreOut(vrfSign.sublist(0, SchnorrkelKeyCost.vrfPreOutLength));
108+
proof = VRFProof.fromBytes(
109+
vrfSign.sublist(SchnorrkelKeyCost.vrfPreOutLength));
110+
}
111+
return _signer.publicKey().vrfVerify(
112+
_SubstrateSr25519SignerUtils.substrateVrfSignScript(message, context),
113+
output,
114+
proof,
115+
verifyScript: _SubstrateSr25519SignerUtils.vrfScript(extra: extra));
116+
}
91117
}
92118

93119
/// Class representing an Substrate SR25519 Verifier for signature verification.

lib/utils/string/string.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,14 @@ class StringUtils {
6262
return value;
6363
}
6464

65+
/// add the '0x' prefix to a hexadecimal string if it exists.
66+
static String add0x(String value) {
67+
if (value.toLowerCase().startsWith("0x")) {
68+
return value;
69+
}
70+
return "0x$value";
71+
}
72+
6573
/// Encodes the given [value] string into a list of bytes using the specified [type].
6674
///
6775
/// The [type] parameter determines the encoding type to use, with UTF-8 being the default.

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: blockchain_utils
22
description: Comprehensive Crypto & Blockchain Toolkit, Pure Dart, Cross-Platform, Encoding, Cryptography, Addresses, Mnemonics, & More.
3-
version: 4.0.0
3+
version: 4.0.1
44
homepage: "https://github.com/mrtnetwork/blockchain_utils"
55
repository: "https://github.com/mrtnetwork/blockchain_utils"
66
Author: mrhaydari.t@gmail.com

0 commit comments

Comments
 (0)