Skip to content

Commit

Permalink
fee packing bug
Browse files Browse the repository at this point in the history
  • Loading branch information
dvush committed Sep 17, 2019
1 parent 5227b04 commit 50c5801
Show file tree
Hide file tree
Showing 8 changed files with 267 additions and 43 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

85 changes: 83 additions & 2 deletions core/models/src/node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::merkle_tree::{PedersenHasher, SparseMerkleTree};
use super::params;
use super::primitives::pack_as_float;
use bigdecimal::BigDecimal;
use failure::bail;
use pairing::bn256;

pub mod account;
Expand Down Expand Up @@ -64,12 +65,92 @@ pub fn pack_fee_amount(amount: &BigDecimal) -> Vec<u8> {
)
}

pub fn convert_to_float(
integer: u128,
exponent_length: usize,
mantissa_length: usize,
exponent_base: u32,
) -> Result<Vec<bool>, failure::Error> {
unimplemented!("proper convert to float");
// let integer = BigDecimal::(integer);
// let exponent_base = BigDecimal::from(exponent_base);
// let mut max_exponent = BigDecimal::from(1u128);
// let max_power = (1 << exponent_length) - 1;
//
// for _ in 0..max_power
// {
// max_exponent = max_exponent * exponent_base;
// }
//
// let max_mantissa = BigDecimal::from((1u128 << mantissa_length) - 1);
//
// if BigDecimal::from(integer) > (max_mantissa * max_exponent) {
// bail!("Integer is too big");
// }
//
// let mut exponent: usize = 0;
// let mut mantissa = integer;
//
// if BigDecimal::from(integer) > max_mantissa.to_u128() {
// // always try best precision
// let exponent_guess = integer / max_mantissa;
// let mut exponent_temp = exponent_guess;
//
// loop {
// if exponent_temp < exponent_base {
// break
// }
// exponent_temp = exponent_temp / exponent_base;
// exponent += 1;
// }
//
// exponent_temp = 1u128;
// for _ in 0..exponent
// {
// exponent_temp = exponent_temp * exponent_base;
// }
//
// if exponent_temp * max_mantissa < integer
// {
// exponent += 1;
// exponent_temp = exponent_temp * exponent_base;
// }
//
// mantissa = integer / exponent_temp;
// }
//
// // encode into bits. First bits of mantissa in LE order
//
// let mut encoding = vec![];
//
// for i in 0..exponent_length {
// if exponent & (1 << i) != 0 {
// encoding.extend(&[true; 1]);
// } else {
// encoding.extend(&[false; 1]);
// }
// }
//
// for i in 0..mantissa_length {
// if mantissa & (1 << i) != 0 {
// encoding.extend(&[true; 1]);
// } else {
// encoding.extend(&[false; 1]);
// }
// }
//
// assert!(encoding.len() == exponent_length + mantissa_length);
//
// Ok(encoding)
}

#[cfg(test)]
mod test {
use crate::node::pack_token_amount;
use super::*;
use bigdecimal::BigDecimal;
#[test]
fn test_pack() {
println!("{:x?}", pack_token_amount(&BigDecimal::from(4)));
// println!("{:x?}", pack_token_amount(&BigDecimal::from(2)));
println!("{:x?}", pack_fee_amount(&BigDecimal::from(1)));
}
}
15 changes: 8 additions & 7 deletions core/models/src/node/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,8 @@ impl Withdraw {

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Close {
// TODO: derrive account address from signature
pub account: AccountAddress,
pub nonce: Nonce,
// TODO: Signature unimplemented
pub signature: TxSignature,
}

Expand Down Expand Up @@ -175,18 +173,21 @@ impl FranklinTx {
}
}

pub fn min_number_of_chunks(&self) -> usize {
// TODO use spec
1
}

pub fn check_signature(&self) -> bool {
match self {
FranklinTx::Transfer(tx) => tx.verify_signature(),
FranklinTx::Withdraw(tx) => tx.verify_signature(),
FranklinTx::Close(tx) => tx.verify_signature(),
}
}

pub fn get_bytes(&self) -> Vec<u8> {
match self {
FranklinTx::Transfer(tx) => tx.get_bytes(),
FranklinTx::Withdraw(tx) => tx.get_bytes(),
FranklinTx::Close(tx) => tx.get_bytes(),
}
}
}

#[derive(Clone, Serialize, Deserialize)]
Expand Down
1 change: 1 addition & 0 deletions core/spec_test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ actix-web = "1.0"
serde = "1.0.90"
serde_derive = "1.0.90"
serde_json = "1.0.0"
hex = "0.3.2"
13 changes: 12 additions & 1 deletion core/spec_test/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use actix_web::{web, App, HttpServer, Responder};
use models::node::tx::{PackedPublicKey, TxSignature};
use log::info;
use models::node::tx::{FranklinTx, PackedPublicKey, TxSignature};
use models::node::AccountAddress;
use serde::{Deserialize, Serialize};
use serde_json::json;

#[derive(Deserialize)]
struct PubkeyPoint {
Expand Down Expand Up @@ -51,13 +53,22 @@ fn check_signature(req: web::Json<SignedMessage>) -> impl Responder {
})
}

fn check_tx_signature(req: web::Json<FranklinTx>) -> impl Responder {
let tx = req.0;
info!("tx: {:#?}", tx);
info!("tx bytes: {}", hex::encode(tx.get_bytes()));
let valid = tx.check_signature();
web::Json(json!(format!("{{ valid: {} }}", valid)))
}

fn main() {
env_logger::init();

HttpServer::new(|| {
App::new()
.service(web::resource("/address").route(web::post().to(address)))
.service(web::resource("/check_signature").route(web::post().to(check_signature)))
.service(web::resource("/check_tx_signature").route(web::post().to(check_tx_signature)))
})
.bind("127.0.0.1:8734")
.expect("Can not bind to port 8734")
Expand Down
2 changes: 1 addition & 1 deletion js/franklin_lib/src/crypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const fsZero = new BN(0);
export const altjubjubCurve = new elliptic.curve.edwards(babyJubjubParams);
const curveZero = altjubjubCurve.point('0', '1');
const chunksPerGenerator = 62;
const addressLen=20;
export const addressLen=20;

let gen1 = altjubjubCurve.point(
'184570ed4909a81b2793320a26e8f956be129e4eed381acf901718dff8802135',
Expand Down
146 changes: 125 additions & 21 deletions js/franklin_lib/src/wallet.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import BN = require('bn.js');
import Axios from 'axios';
import {
altjubjubCurve,
pedersenHash,
musigPedersen,
privateKeyFromSeed,
privateKeyToPublicKey,
pubkeyToAddress,
} from './crypto';
import { curve } from 'elliptic';
import EdwardsPoint = curve.edwards.EdwardsPoint;
import {Contract, ethers} from 'ethers';
import edwards = curve.edwards;
import {packAmount, packFee} from "./utils";

// ! can't import from 'ethers/utils' it won't work in the browser.
type BigNumber = ethers.utils.BigNumber;
Expand All @@ -19,12 +20,41 @@ const bigNumberify = ethers.utils.bigNumberify;
const IERC20Conract = require("../abi/IERC20");
const franklinContractCode = require("../abi/Franklin");

export type Address = string;
export type Address = Buffer;


export class FranklinProvider {
constructor(public providerAddress: string = 'http://127.0.0.1:3000', public contractAddress: string = process.env.CONTRACT_ADDR) {}

static prepareTransferRequestForNode(tx: TransferTx, signature) {
let req: any = tx;
req.type = "Transfer";
req.from = `0x${tx.from.toString("hex")}`;
req.to = `0x${tx.to.toString("hex")}`;
req.amount = bigNumberify(tx.amount).toString();
req.fee = bigNumberify(tx.fee).toString();
req.signature = signature;
return req;
}

static prepareWithdrawRequestForNode(tx: WithdrawTx, signature) {
let req: any = tx;
req.type = "Withdraw";
req.account = `0x${tx.account.toString("hex")}`;
req.amount = bigNumberify(tx.amount).toString();
req.fee = bigNumberify(tx.fee).toString();
req.signature = signature;
return req;
}

static prepareCloseRequestForNode(tx: CloseTx, signature) {
let req: any = tx;
req.type = "Close";
req.account = `0x${tx.account.toString("hex")}`;
req.signature = signature;
return req;
}

async submitTx(tx) {
return await Axios.post(this.providerAddress + '/api/v0.1/submit_tx', tx).then(reps => reps.data);
}
Expand Down Expand Up @@ -62,35 +92,109 @@ interface ETHAccountState {
lockedBlocksLeft: number[],
}

export interface TransferTx {
from: Address,
to: Address,
token: number,
amount: BigNumberish,
fee: BigNumberish,
nonce: number,
}

export interface WithdrawTx {
account: Address,
eth_address: String,
token: number,
amount: BigNumberish,
fee: BigNumberish,
nonce: number,
}

export interface CloseTx {
account: Address,
nonce: number,
}

export class WalletKeys {
publicKey: edwards.EdwardsPoint;

constructor(public privateKey: BN) {
this.publicKey = privateKeyToPublicKey(privateKey);
}

signTransfer(tx: TransferTx) {
let type = Buffer.from([5]); // tx type
let from = tx.from;
let to = tx.to;
let token = Buffer.alloc(2);
token.writeUInt16BE(tx.token,0);
let bnAmount = new BN(bigNumberify(tx.amount).toString() );
let amount = packAmount(bnAmount);
let bnFee = new BN(bigNumberify(tx.fee).toString());
let fee = packFee(bnFee);
let nonce = Buffer.alloc(4);
nonce.writeUInt32BE(tx.nonce, 0);
let msg = Buffer.concat([type, from, to, token, amount, fee, nonce]);
return musigPedersen(this.privateKey, msg);
}

signWithdraw(tx: WithdrawTx) {
let type = Buffer.from([3]);
let account = tx.account;
let eth_address = Buffer.from(tx.eth_address.slice(2),"hex")
let token = Buffer.alloc(2);
token.writeUInt16BE(tx.token,0);
let bnAmount = new BN(bigNumberify(tx.amount).toString());
let amount = bnAmount.toBuffer("be", 16);
let bnFee = new BN(bigNumberify(tx.fee).toString());
let fee = packFee(bnFee);

let nonce = Buffer.alloc(4);
nonce.writeUInt32BE(tx.nonce, 0);

let msg = Buffer.concat([type, account, eth_address, token, amount, fee, nonce]);
return musigPedersen(this.privateKey, msg);
}

signClose(tx: CloseTx) {
let type = Buffer.from([4]);
let account = tx.account;
let nonce = Buffer.alloc(4);
nonce.writeUInt32BE(tx.nonce, 0);

let msg = Buffer.concat([type, account, nonce]);
return musigPedersen(this.privateKey, msg);
}
}


export class Wallet {
address: Address;
privateKey: BN;
publicKey: EdwardsPoint;
walletKeys: WalletKeys;

supportedTokens: Token[];
franklinState: FranklinAccountState;
ethState: ETHAccountState;

constructor(seed: Buffer, public provider: FranklinProvider, public ethWallet: ethers.Signer, public ethAddress: string) {
let {privateKey, publicKey} = privateKeyFromSeed(seed);
this.privateKey = privateKey;
this.publicKey = publicKey;
this.address = `0x${pubkeyToAddress(this.publicKey).toString("hex")}`;
let {privateKey} = privateKeyFromSeed(seed);
this.walletKeys = new WalletKeys(privateKey);
this.address = pubkeyToAddress(this.walletKeys.publicKey);
}

async deposit(token: Token, amount: BigNumberish) {
const franklinDeployedContract = new Contract(this.provider.contractAddress, franklinContractCode.interface, this.ethWallet);
const franklinAddressBinary = Buffer.from(this.address.substr(2), "hex");
if (token.id == 0) {
const tx = await franklinDeployedContract.depositETH(franklinAddressBinary, {value: amount});
return tx.hash;
} else {
const erc20DeployedToken = new Contract(token.address, IERC20Conract.abi, this.ethWallet);
await erc20DeployedToken.approve(franklinDeployedContract.address, amount);
const tx = await franklinDeployedContract.depositERC20(erc20DeployedToken.address, amount, franklinAddressBinary,
{gasLimit: bigNumberify("150000"), value: parseEther("0.001")});
return tx.hash;
}
// const franklinDeployedContract = new Contract(this.provider.contractAddress, franklinContractCode.interface, this.ethWallet);
// const franklinAddressBinary = Buffer.from(this.address.substr(2), "hex");
// if (token.id == 0) {
// const tx = await franklinDeployedContract.depositETH(franklinAddressBinary, {value: amount});
// return tx.hash;
// } else {
// const erc20DeployedToken = new Contract(token.address, IERC20Conract.abi, this.ethWallet);
// await erc20DeployedToken.approve(franklinDeployedContract.address, amount);
// const tx = await franklinDeployedContract.depositERC20(erc20DeployedToken.address, amount, franklinAddressBinary,
// {gasLimit: bigNumberify("150000"), value: parseEther("0.001")});
// return tx.hash;
// }
}

async widthdrawOnchain(token: Token, amount: BigNumberish) {
Expand Down
Loading

0 comments on commit 50c5801

Please sign in to comment.