Skip to content

Commit

Permalink
Merge pull request #3 from jpmorganchase/features/PADLbn254
Browse files Browse the repository at this point in the history
Features/pad lbn254
  • Loading branch information
shaltiel authored Feb 14, 2025
2 parents 2ea54ec + ae16cab commit 6221e32
Show file tree
Hide file tree
Showing 54 changed files with 3,549 additions and 2,110 deletions.
14 changes: 4 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,21 @@
# PADL
# PADL
## Customized & Efficient ZK toolkit for Private and auditable Ledger

PADL is based on zero-knowledge proofs for inter-parties framework for exploring applications for financial institutes. Padl utilises Sigma Protocols and range proofs on homomorphic multi-asset ledger with smart-contracts capability to verify transactions on chain.

## Env for Private Auditable And Distributed Ledger
- Padl includes rust lib 'zkbp' wrapped in python, so can be used directly as a python package for using crypto primitives and proof generations.
Rust implementation is highly based on secp256k1 from ZenGo-X/curv and bulletproofs as well as extended ZKP with sigma protocols+range proofs.
Rust implementation is highly based on bn254 (Ark-bn254) and secp256k1 from ZenGo-X/curv with bulletproofs, as well as extended ZKP with sigma protocols+range proofs.
- Padl Smart-Contracts developed in solidity based on ECC for deployment on evm network, providing fast proofs verification for multi-assets tx and implementation of padl-private token.


### Env. Prerequests
1. python > 3.8 and Rust.
2. For testing on smart contracts: `nodejs`, and for local evm testing env., for example ganache-cli, OpenZeppelin contracts such as ERC20.

2. For testing on EVM smart contracts: `nodejs`, and for local evm testing env., for example ganache-cli or geth.

### PADL Installation
3. run `python setup.py init`

## openzeppelin-contracts
To run the example padl_deployERC.py, need to run `python setup.py contract` to download the openzeppelin-contracts library.

## Run python `serv.py` under the dictionary `PADL\cloud_server\python_storage`


See more examples (pyledger/examples), and tutorials under (./tutorials).

## PADL Paper
Expand Down
59 changes: 43 additions & 16 deletions pyledger/Proof_Generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,58 @@
path = os.path.realpath(__file__)
parent_dir = str(Path(path).parents[1]) # go up 2 levels [1] to '/zkledgerplayground/'
sys.path.append(parent_dir)
from pyledger.zkutils import Commit, Token, r_blend, Secp256k1 # interface to zkbp.
from pyledger.zkutils import Commit, Token, r_blend, Secp256k1, curve_util # interface to zkbp.
from pyledger.extras.injective_utils import InjectiveUtils
BITS = 64
BITS = 32
MAX = int(2 ** (BITS / 4))


def ptsol(point_str):
return (int(zkbp.from_str(point_str["point"]).x), int(zkbp.from_str(point_str["point"]).y))


def ptsol_arr(point_str_arr):
return [(int(zkbp.from_str(point_str["point"]).x), int(zkbp.from_str(point_str["point"]).y)) for point_str in
point_str_arr]


def ssol(scalar_str):
return int((scalar_str["scalar"]), 16)

class ProofGenerator:
"""
This object is for generating proofs.
"""


def generate_proof_of_asset(self, v, r, n_bit=int(BITS/2)):
from pyledger.Proof_verification import Auditing
def generate_proof_of_asset(self, v, r, n_bit=BITS, smart_contract=False):
# from pyledger.Proof_verification import Auditing
start = time.time()
range_proof = zkbp.range_proof_single(n_bit=n_bit, val=v, gh=zkbp.gen_GH(), r=r.val)
done = time.time()
elapsed = done - start

if smart_contract:
sol_proof= self.sol_format_proof_of_asset(json.loads(range_proof),v,r,n_bit)
# rejecting smaller than 32 scalars for appropriate hashing on contract.
for val in sol_proof:
if isinstance(val,int):
if (val.bit_length() + 7) // 8 <32:
return self.generate_proof_of_asset(v, r, n_bit=BITS, smart_contract=True)
# returning solidity formatted proof
return sol_proof
# returning json proof
return range_proof


def sol_format_proof_of_asset(self, range_proof_json,v,r,n_bit):
gh = zkbp.gen_GH()
cm = Commit(gh, v, r)
ghvec = json.loads(zkbp.ghvec(n_bit))
range_proof_sol = ((ptsol(range_proof_json["A"]), ptsol(range_proof_json["S"]), ptsol(range_proof_json["T1"]),
ptsol(range_proof_json["T2"]), ssol(range_proof_json["tau_x"]), ssol(range_proof_json["miu"]),
ssol(range_proof_json["tx"]), int(range_proof_json["inner_product_proof"]["a_tag"], 16),
int(range_proof_json["inner_product_proof"]["b_tag"], 16), ptsol({"point": gh.g}),
ptsol({"point": gh.h}), ptsol({"point": cm.eval.get}),
ptsol_arr(range_proof_json["inner_product_proof"]["L"]),
ptsol_arr(range_proof_json["inner_product_proof"]["R"]), ptsol_arr(ghvec[0]),
ptsol_arr(ghvec[1])))
return range_proof_sol

def generate_proof_of_balance(self, tx):
from pyledger.Proof_verification import Auditing
Expand Down Expand Up @@ -147,9 +178,6 @@ def generate_asset_ratio_proof_(self, n_bit=BITS, asset=0, n=1, d=2):
range_proof = zkbp.range_proof_single(n_bit=n_bit, val=sum_v_ratio, gh=self.gh, r=sum_r_ratio.val)
return range_proof

########################################################################################################################################
########################################################################################################################################


def generate_range_proof_positive_commitment_erc(self, val, pub_key):
"""generate the range proof positive commitment
Expand Down Expand Up @@ -192,8 +220,6 @@ def generate_range_proof_positive_commitment_erc(self, val, pub_key):
return rpr, t, c, r




def generate_range_proof_positive_commitment(self, val, id, ledger, smart_contract=True):
"""generate the range proof positive commitment
Expand Down Expand Up @@ -241,10 +267,11 @@ def generate_range_proof_positive_commitment(self, val, id, ledger, smart_contra
r = reduce(lambda x, y: x+y, rs)

if smart_contract:
rpr = {"cm": Secp256k1.get_xy(c.get), "pr1": eqprs[0], "pr2": eqprs[1], "pr3": eqprs[2], "pr4": eqprs[3]}
rpr = {"cm": curve_util.get_xy(c.get), "pr1": eqprs[0], "pr2": eqprs[1], "pr3": eqprs[2], "pr4": eqprs[3]}
return rpr, t, c, r
else :
return prs, t, c, r




16 changes: 12 additions & 4 deletions pyledger/Proof_verification.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@
sys.path.append(parent_dir)
from pyledger.zkutils import Commit, Token, r_blend, Secp256k1 # interface to zkbp.
from pyledger.extras.injective_utils import InjectiveUtils
BITS = 64
MAX = int(2 ** (BITS / 4))
BITS = 32
MAX = int(2 ** 16)
# MAX = int(2 ** (BITS / 4))




Expand All @@ -36,7 +38,7 @@ class Auditing:
def validate_proof_of_balance(tx):
cms = [c.cm for c in tx]
sum_cms = reduce(lambda x, y: zkbp.add_value_commits(x, y), cms)
if sum_cms == len(sum_cms) * '0':
if zkbp.from_str(sum_cms).is_zero():
for t in tx: t.P_B = True
return True
else:
Expand All @@ -45,8 +47,10 @@ def validate_proof_of_balance(tx):


@staticmethod
def valdiate_proof_of_asset(txs, zero_line, i, tx, nbit=int(BITS/2), asset=0):
def valdiate_proof_of_asset(txs, zero_line, i, tx, nbit=int(BITS), asset=0):
range_proof = tx[i].P_A
if isinstance(range_proof,list):
range_proof = tx[i].P_A[0] # the first index is proof A, the second is eq proof which can be removed.
cms = [x[asset][i].cm for x in txs if len(x) > asset]
cms.append(zero_line[i][asset].cm) # issued asset value
cms.append(tx[i].cm) # new Tx commit
Expand All @@ -57,6 +61,10 @@ def valdiate_proof_of_asset(txs, zero_line, i, tx, nbit=int(BITS/2), asset=0):
result = zkbp.range_proof_single_verify(range_proof, nbit, zkbp.gen_GH(), zkbp.from_str(tx[i].cm_))
assert result, "proof of asset is failed"

@staticmethod
def valdiate_proof_of_positive_commit(cm:str, range_proof:str, nbit=int(BITS)):
result = zkbp.range_proof_single_verify(range_proof, nbit, zkbp.gen_GH(), zkbp.from_str(cm))
assert result, "proof of asset is failed"

@staticmethod
def valdiate_proof_of_consistency(pub_keys, i, tx):
Expand Down
3 changes: 0 additions & 3 deletions pyledger/contracts/Auction.sol
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
pragma solidity ^0.8.0;
import "./PADLOnChain.sol";

/// @title A wrapper for auction, including the ending time of opening the auction and issuer approve the transaction
/// @author Applied research, Global Tech., JPMorgan Chase, London
/// @notice This is an code for research and experimentation.


contract Auction is PADLOnChain{
event auctionOpen(string msg, uint time);
event auctionClosed(string msg, uint id);
Expand Down
16 changes: 16 additions & 0 deletions pyledger/contracts/Interfaces/BNInterface.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
pragma solidity ^0.8.19;
/// @title Verification for proof of equivalence in transaction
/// @author Applied research, Global Tech., JPMorgan Chase, London
/// @notice This is an code for research and experimentation.

struct BN254Point{
uint256 x;
uint256 y;
}

abstract contract BNInterface {

function add(BN254Point calldata point1, BN254Point calldata point2) public virtual returns (BN254Point memory ret);
function mul(BN254Point calldata point1, uint256 scalar) public virtual returns (BN254Point memory ret);
function neg(BN254Point calldata p) public virtual returns (BN254Point memory);
}
29 changes: 29 additions & 0 deletions pyledger/contracts/Interfaces/ConsistencyProofInterface.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
pragma solidity ^0.8.28;
/// @title Verification for proof of equivalence in transaction
/// @author Applied research, Global Tech., JPMorgan Chase, London
/// @notice This is an code for research and experimentation.
import "../Interfaces/BNInterface.sol";

struct consistencyProofSolR{
BN254Point t1;
BN254Point t2;
uint256 s1;
uint256 s2;
uint256 challenge;
BN254Point pubkey;
BN254Point cm;
BN254Point tk;
BN254Point chalcm;
BN254Point chaltk;
BN254Point s2pubkey;
BN254Point s1g;
BN254Point s2h;
}

abstract contract ConsistencyProofInterface {

function getConsistencyHash(consistencyProofSolR memory prsol) public virtual returns(uint256);
function pushPointToHash(bytes memory b, uint256 x, uint256 y) public virtual returns(bytes memory);
function closeHash(bytes memory b) public virtual returns (uint256);
function verify(consistencyProofSolR memory prsol) public virtual returns(bool);
}
21 changes: 21 additions & 0 deletions pyledger/contracts/Interfaces/EquivalenceProofInterface.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
pragma solidity ^0.8.20;
/// @title Verification for proof of equivalence in transaction
/// @author Applied research, Global Tech., JPMorgan Chase, London
/// @notice This is an code for research and experimentation.
import "../Interfaces/BNInterface.sol";
import "../Interfaces/EquivalenceProofInterface.sol";

struct eqProofSolR{
BN254Point pk;
BN254Point pktrand;
uint256 chalrsp;
}

abstract contract EquivalenceProofInterface {

function pushPointToHash(bytes memory b, uint256 x, uint256 y) public virtual returns(bytes memory);
function closeHash(bytes memory b) public virtual returns (uint256);
function getChallenge(eqProofSolR memory prsol, BN254Point memory h2r) public virtual returns (uint256);
function verify(eqProofSolR memory prsol, BN254Point memory h2r) public virtual returns (bool);

}
66 changes: 66 additions & 0 deletions pyledger/contracts/Interfaces/PADLOnChainInterface.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/// @title Private and auditable transaction via on-chain verification
/// @author Applied research, Global Tech., JPMorgan Chase, London
/// @notice This is an code for research and experimentation.
pragma solidity ^0.8.20;

//import "../ZK_proof/bn254.sol";
//import {Bulletproof} from "../ZK_proof/RangeVerifier.sol";
//import {ConsistencyProofBN} from "../ZK_proof/ConsistencyProofBN.sol";
//import {EquivalenceProofBN} from "../ZK_proof/EquivalenceProofBN.sol";
//import {Rangeproof} from "../ZK_proof/RangeVerifier.sol";
import "../Interfaces/BNInterface.sol";
import "../Interfaces/RangeProofInterface.sol";
import "../Interfaces/ConsistencyProofInterface.sol";
import "../Interfaces/EquivalenceProofInterface.sol";


abstract contract PADLOnChainInterface {
struct cmtk {
BN254Point cm;
BN254Point tk;
}

struct txcell {
BN254Point cm;
BN254Point tk;
BN254Point compcm;
BN254Point comptk;
eqProofSolR peq;
consistencyProofSolR pc;
consistencyProofSolR pc_;
Rangeproof ppositive;
}

function isPermitted(address _add) public virtual returns (bool);
function addRequests(address _add, string memory _zl, uint _amt) public virtual;
function addParticipant(address _add) public virtual;
function getTotalBalance() public virtual view returns (uint);
function retrieveParticipant(uint i) public virtual view returns (address);
function retrieveNumberOfParticipants() public virtual view returns (uint);
function storePublicKey(string memory _pk, address _add) public virtual;
function retrievePk(address _add) public virtual view returns (string memory);
function retrieveAllPks() public virtual view returns (string memory);
function retrieveZeroLine(address _add) public virtual view returns (string memory);
function addZeroLine(string memory _zl, address _add) public virtual;
function retrieveTxnLength() public virtual view returns(uint) ;
function storeIntCMTK(cmtk[][] memory _p) public virtual;
function addstorageidentifier(string memory _idnt) public virtual;
function retrieveCommitsTokens() public virtual returns(cmtk[][] memory);
function retrieveIdentifier() public virtual returns(string memory);
function voteTxn() public virtual;
function checkTxnApproval() public virtual returns(bool);
function resetVotes() public virtual;
function updateState() public virtual;
function approveTxn() public virtual;
function approveTxnIssuer() virtual public ;
function clearTxn() public virtual;
function retrieveTxn(uint i) public virtual returns(string memory);
function setGovRules(string memory gov) virtual public ;
function retrieveGovarnenceRules() public virtual returns(string memory);
function addZeroLineToState(cmtk [] memory zls) public virtual;
function retrieveStateId(uint256 p) public virtual returns (cmtk[] memory);
function processTx(txcell[] memory ctx, uint256 asset_id) public virtual returns (bool);
function checkSenderCell(txcell memory ctxid, address add, BN254Point memory h2rd) public virtual returns (bool);
function checkReceiverCell(txcell memory ctx) public virtual returns (bool);

}
32 changes: 32 additions & 0 deletions pyledger/contracts/Interfaces/RangeProofInterface.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
/// @title Verification for proof of equivalence in transaction
/// @author Applied research, Global Tech., JPMorgan Chase, London
/// @notice This is an code for research and experimentation.
//import "./bn254.sol";
import "../Interfaces/BNInterface.sol";
//import {BN254} from "./bn254.sol";

struct Rangeproof{
BN254Point A;
BN254Point S;
BN254Point T1;
BN254Point T2;
uint256 tau_x;
uint256 miu;
uint256 tx;
uint256 a_tag;
uint256 b_tag;
BN254Point G;
BN254Point H;
BN254Point Com;
BN254Point[5] L;
BN254Point[5] R;
BN254Point[32] g_vec;
BN254Point[32] h_vec;
// BN254Point[32] yi_vec;
}

abstract contract RangeProofInterface {
function verify_range_proof(Rangeproof calldata proof) public virtual returns (bool);
}
Loading

0 comments on commit 6221e32

Please sign in to comment.