BLSCT Protocol
This section will describe the cryptography behind BLSCT, the novel protocol which we used to build NavCoin’s new private token xNAV.
For a wallet to create and receive BLSCT transactions, it needs to own a set of BLS keys. Let \(KDF(k, p)\) be a key derivation function where k
is a BLS private key and p
a derivation path, and m
the wallet’s master secret key. We use G1
from the pairing-friendly elliptic curve BLS12-381 and let g
be a G1
generator. Let H
be a secure hash function whose output is of 256-bit length and HG1
a hash function whose output is mapped as a G1
element.
The first steps are to calculate:
A master blinding key: \(bmk = KDF(m, 130'/1')\)
A master view key: \(vmk = KDF(m, 130'/0'/0')\)
A master spend key: \(smk = KDF(m, 130'/0'/1')\)
A wallet can then generate the needed keys to construct an arbitrary number of addresses where coins can be received. Wallets generate their SAi
-th address \(SAi = (0,1,2,...)\) in their Ai
-th account \(Ai = (0,1,2,...)\) as a pair of public keys (C, D)
where:
Wallets must store D
in the wallet’s database registered to the index (Ai, SAi)
as an integer pair. Addresses are a Base58Check representation of the keys (C, D)
using 73
and 33
as mainnet Version bytes. When a wallet wants to send funds to an address, it must:
Decode and extract
(C, D)
from the address.Maintain an incremental counter of blinding addresses
Bi
.Generate an ephemeral private key \(e = KDF(bmk, Bi++)\)
Calculate the ephemeral public key \(E = e*g\)
Generate the output’s public key \(R = e*D\)
Generate the spending key \(P = H(e*C)*g+D\)
Generate a shared secret \(S = e*C\)
The wallet must construct a per-output range-proof bp
to prove that the hidden amount v
is positive and within the allowed range. It is allowed to attach an encrypted message memo
limited to 54 bytes only viewable by the transaction’s recipient. Some of the scalars used in the proof creation are calculated from the shared secret S
.
The commitment’s secret key gamma will sign the message BLSCTBALANCE
to create a signature BPSO
, which will serve to prove later that the transaction creates no new coins. Constructing the signature using the basic scheme and a constant message is secure against a rogue public-key attack combined with a valid Bulletproofs range-proof. An attacker can not create it without knowledge of the secret key gamma.
The output’s ephemeral key e
will sign the output’s hash to create a signature BSO
using the augmented scheme.
The range proof bp
and the public keys E
, R
, and P
will be attached to a transaction’s output when it targets a private address. Transactions that include a BLSCT output have their version bit 10
set to 1
. Both public and BLSCT outputs can combine in the same transaction.
When a client sees this output, he will determine whether it belongs to him or not by performing the following checks:
Calculate \(D' = P - H(vmk*R)*g\) and check if its wallet’s database has it registered to an index
(Ai', SAi')
.Calculate \(S' = vmk * R\)
Derive
alpha
,rho
,tau1
andtau2
andgamma'
fromS'
.Verify if the range proof
bp
is valid.Calculate \(ex = (mu - rho*x) - alpha\) and \(ex2 = ((taux - tau2*x^2 - gamma*z^2) * x^{-1}) - tau1\)
Extract the amount as \(v' = ex \& 0xFFFFFFFFFFFFFFFF\)
Extract the encrypted message as \(memo' = ex2 || ex >> 64\)
Check if the range-proof value’s commitment equals to \(gamma'*g + v'*HG1(g||"bulletproof"||0)\)
When the client wants to spend this output, it must set the spending transaction’s version bit 11
to 1
. It can calculate the output’s private spending key as \(p = H(vmk*R) + smk + H("SubAddress"||vmk||Ai'||SAi')\). The private key p
will sign the transaction input hash using the augmented scheme to produce the signature BSI
.
The extracted commitment’s secret key gamma'
will sign the message BLSCTBALANCE
to create a signature BPSI
.
The wallet will store the aggregation of all of the transaction’s BSI
s and BSO
s in its BLS transaction signature field as BS
. The transaction’s BLS balance signature will result from aggregating all the BPSI
s and BPSO
s signatures as BPS
.
Every transaction must include an output with a transparent amount whose script is the provably unspendable OP_RETURN
representing the sender’s fee. Transactions are not allowed to combine public and private inputs.
A validator can determine if a transaction is correct:
By verifying that
BPS
is a valid signature by definingpkBal
as, for each transaction’s inputprevOut
, the sum of \(prevOut.bp.v\) if it is private or \(prevOut.amount*HG1(g||"bulletproof"||0)\) if it is public, minus the sum of, for each transaction’s outputout
, \(out.bp.v\) if it is private or \(out.amount*HG1(g||"bulletproof"||0)\) if it is public, and usingpkBal
as the signer’s public key andBLSCTBALANCE
as the message of the basic scheme,by verifying that
BS
is a valid signature using the augmented scheme withP, H(tx_in)
for each transaction’s input as inputs to the verify signature function, andE, H(tx_out)
from each transaction’s output,and by verifying that for each output, its range proof
bp
is validated correctly.