Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce BLS library into codebase #1823

Closed
blukat29 opened this issue Apr 7, 2023 · 3 comments
Closed

Introduce BLS library into codebase #1823

blukat29 opened this issue Apr 7, 2023 · 3 comments
Assignees
Labels

Comments

@blukat29
Copy link
Contributor

blukat29 commented Apr 7, 2023

Is your request related to a problem? Please describe.
Klaytn needs to bring in BLS algorithm for RANDAO, optimized consensus and EIP-2537.

BLS functionality can be split into two layers:

  • BLS12-381 arithmetic: functions like G1.Add(P,Q). An example usage is the EIP-2537 precompiles.
  • BLS (simple or aggregate) signature: functions like Sign() and AggregateVerify(). Example usages are RANDAO and block signatures.

Klaytn should need both layers.

Describe the solution you'd like
Below are potential Go open sources we can use.

I propose to combine approaches of geth and prysm.

  • Use geth/crypto/bls12381 for BLS12-381 arithmetic.
  • Import supranational/blst and write klaytn/bls wrapper for BLS signatures.

To summarize,

Layer geth (EL) celo (CL+EL) prysm (CL) klaytn (CL+EL)
BLS (simple and aggregate) signature (not needed) celo/crypto/bls +
celo-bls-go (BLS12-377)
prysm/crypto/bls +
supranational/blst
klaytn/crypto/bls +
supranational/blst
BLS12-381 arithmetic geth/crypto/bls12381 celo/crypto/bls12381 (not needed) klaytn/crypto/bls12381

Describe alternatives you've considered
Instead of adding source code to klaytn/klaytn repo, we might simply import geth and prysm internal packages.

Additional context
Other cases:

Benchmark tests

  • BLS library benchmark (2023.04) - Google Sheets.pdf
  • geth/crypto/bls12381 performance is consistent with EIP-2537 gas pricing.
  • supranational/blst takes up to 2ms to Sign once, Verify once, or AggregateVerify 100 signatures. I think it is enough for consensus purposes.
  • (G1=sig,G2=pub) mode is less than 0.5ms/op faster than (G1=pub,G2=sig) mode. I think performance is not a critical factor in choosing the mode.
@blukat29 blukat29 self-assigned this Apr 7, 2023
@exalate-issue-sync
Copy link

Exalate commented: Issue Created by: blukat29

This was referenced Apr 11, 2023
@aidan-kwon
Copy link
Member

closed via #1824 #1825

@ian0371
Copy link
Contributor

ian0371 commented Apr 24, 2024

For BLS key derivation and pop generation, these are the requirements:

  • deriving BLS key from the input keying material (IKM) should be possible. (in our case, IKM is the node key)
  • signing public key with a domain separator tag (DST) for pop should be possible.
    • DST for pop: BLS_POP_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_
    • fyi, DST for sig: BLS_SIG_...

In terms of ERC-2333, the seed is the nodekey, and the derived BLS key is master_SK, where derive_master_SK(seed) -> master_SK.

For typescript implementation, there is no library that supports both features. Thus,

Sample code)

import loadBls from "bls-signatures";

import { deriveKeyFromEntropy } from "@chainsafe/bls-keygen";

type Unpromisify<T> = T extends Promise<infer U> ? U : T;

let BLS: Unpromisify<ReturnType<typeof loadBls>>;

function deriveKey(ikm: Uint8Array) {
  return deriveKeyFromEntropy(ikm);
}

function generatePop(privkey: Uint8Array) {
  const blskey = BLS.PrivateKey.from_bytes(privkey, true);
  const pop = BLS.PopSchemeMPL.pop_prove(blskey);
  return pop.serialize();
}

async function main() {
  BLS = await loadBls();

  const nodekey = Buffer.from(
    "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
    "hex",
  );
  const blskey = deriveKey(nodekey);
  const pop = generatePop(blskey);
  console.log("blskey", Buffer.from(blskey).toString("hex"));
  console.log("pop", Buffer.from(pop).toString("hex"));
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants