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

support perpetual-contract branch of circuit #46

Merged
merged 12 commits into from
Nov 2, 2023
2 changes: 2 additions & 0 deletions binding_tests/interface_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ func TestSignOrderMatching(t *testing.T) {
*big.NewInt(323289),
*big.NewInt(135),
true,
false,
2,
5,
nil,
Expand All @@ -165,6 +166,7 @@ func TestSignOrderMatching(t *testing.T) {
*big.NewInt(323355),
*big.NewInt(135),
false,
false,
2,
5,
nil,
Expand Down
1 change: 1 addition & 0 deletions bindings/sdk/src/ffi.udl
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ interface Order {
BigUint amount,
BigUint price,
boolean is_sell,
boolean has_subsidy,
u8 fee_ratio1,
u8 fee_ratio2,
ZkLinkSignature ?signature
Expand Down
1 change: 1 addition & 0 deletions bindings/sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use zklink_sdk_signers::zklink_signer::signature::{PackedSignature, ZkLinkSignat

use zklink_sdk_types::basic_types::tx_hash::TxHash;
use zklink_sdk_types::basic_types::zklink_address::ZkLinkAddress;
use zklink_sdk_types::basic_types::GetBytes;
use zklink_sdk_types::basic_types::{
AccountId, BigUint, BlockNumber, ChainId, EthBlockId, Nonce, PairId, PriorityOpId, SlotId,
SubAccountId, TimeStamp, TokenId,
Expand Down
2 changes: 1 addition & 1 deletion interface/src/sign_change_pubkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ use std::sync::Arc;
use zklink_sdk_signers::eth_signer::packed_eth_signature::PackedEthSignature;
use zklink_sdk_signers::eth_signer::pk_signer::EthSigner;
use zklink_sdk_signers::zklink_signer::pk_signer::ZkLinkSigner;
use zklink_sdk_types::basic_types::GetBytes;
use zklink_sdk_types::basic_types::ZkLinkAddress;
#[cfg(not(feature = "ffi"))]
use zklink_sdk_types::prelude::TxSignature;
#[cfg(feature = "ffi")]
use zklink_sdk_types::tx_type::change_pubkey::Create2Data;
use zklink_sdk_types::tx_type::change_pubkey::{ChangePubKey, ChangePubKeyAuthData};
use zklink_sdk_types::tx_type::TxTrait;

#[cfg(not(feature = "ffi"))]
pub fn sign_change_pubkey(
Expand Down
4 changes: 2 additions & 2 deletions interface/src/sign_forced_exit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
use std::sync::Arc;
use zklink_sdk_signers::zklink_signer::error::ZkSignerError;
use zklink_sdk_signers::zklink_signer::pk_signer::ZkLinkSigner;
use zklink_sdk_types::basic_types::GetBytes;
use zklink_sdk_types::prelude::TxSignature;
use zklink_sdk_types::tx_type::forced_exit::ForcedExit;
use zklink_sdk_types::tx_type::TxTrait;

pub fn sign_forced_exit(
zklink_signer: &ZkLinkSigner,
Expand Down Expand Up @@ -52,7 +52,7 @@ mod tests {
withdraw_to_l1: false,
timestamp: TimeStamp(1649749979),
};
let tx = ForcedExit::new(builder);
let tx = builder.build();

let signature = sign_forced_exit(&zk_signer, tx).unwrap();
assert!(signature.eth_signature.is_none());
Expand Down
2 changes: 1 addition & 1 deletion interface/src/sign_order.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
use std::sync::Arc;
use zklink_sdk_signers::zklink_signer::error::ZkSignerError;
use zklink_sdk_signers::zklink_signer::pk_signer::ZkLinkSigner;
use zklink_sdk_types::basic_types::GetBytes;
use zklink_sdk_types::tx_type::order_matching::Order;
use zklink_sdk_types::tx_type::TxTrait;
#[cfg(not(feature = "ffi"))]
pub fn sign(order: &mut Order, signer: &ZkLinkSigner) -> Result<(), ZkSignerError> {
let bytes = order.get_bytes();
Expand Down
2 changes: 1 addition & 1 deletion interface/src/sign_order_matching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
use std::sync::Arc;
use zklink_sdk_signers::zklink_signer::error::ZkSignerError;
use zklink_sdk_signers::zklink_signer::pk_signer::ZkLinkSigner;
use zklink_sdk_types::basic_types::GetBytes;
use zklink_sdk_types::prelude::TxSignature;
use zklink_sdk_types::tx_type::order_matching::OrderMatching;
use zklink_sdk_types::tx_type::TxTrait;

pub fn sign_order_matching(
zklink_signer: &ZkLinkSigner,
Expand Down
4 changes: 2 additions & 2 deletions interface/src/sign_transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ use crate::error::SignError;
use std::sync::Arc;
use zklink_sdk_signers::eth_signer::pk_signer::EthSigner;
use zklink_sdk_signers::zklink_signer::pk_signer::ZkLinkSigner;
use zklink_sdk_types::basic_types::GetBytes;
use zklink_sdk_types::prelude::TxSignature;
use zklink_sdk_types::tx_type::transfer::Transfer;
use zklink_sdk_types::tx_type::TxTrait;

pub fn sign_transfer(
eth_signer: &EthSigner,
Expand Down Expand Up @@ -57,7 +57,7 @@ mod tests {
nonce: Nonce(1),
timestamp: TimeStamp(1646101085),
};
let tx = Transfer::new(builder);
let tx = builder.build();

let signature = sign_transfer(&eth_signer, &zk_signer, tx, "USD").unwrap();
let eth_sign = signature
Expand Down
6 changes: 3 additions & 3 deletions interface/src/sign_withdraw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ use crate::error::SignError;
use std::sync::Arc;
use zklink_sdk_signers::eth_signer::pk_signer::EthSigner;
use zklink_sdk_signers::zklink_signer::pk_signer::ZkLinkSigner;
#[cfg(feature = "ffi")]
use zklink_sdk_types::basic_types::GetBytes;
use zklink_sdk_types::prelude::TxSignature;
use zklink_sdk_types::tx_type::withdraw::Withdraw;
#[cfg(feature = "ffi")]
use zklink_sdk_types::tx_type::TxTrait;
use zklink_sdk_types::tx_type::ZkSignatureTrait;

pub fn sign_withdraw(
Expand Down Expand Up @@ -61,7 +61,7 @@ mod tests {
withdraw_fee_ratio: 50,
timestamp: TimeStamp(1649749979),
};
let tx = Withdraw::new(builder);
let tx = builder.build();
let eth_signer = eth_pk.into();
let zk_signer = ZkLinkSigner::new_from_eth_signer(&eth_signer).unwrap();
let signature = sign_withdraw(&eth_signer, &zk_signer, tx, "USD").unwrap();
Expand Down
35 changes: 33 additions & 2 deletions signers/src/zklink_signer/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ pub(crate) fn rescue_hash_elements(input: &[Fr]) -> Fr {
})
}

pub(crate) fn rescue_hash_tx_msg(msg: &[u8]) -> Vec<u8> {
pub fn rescue_hash_tx_msg(msg: &[u8]) -> Vec<u8> {
let mut msg_bits = bytes_into_be_bits(msg);
assert!(msg_bits.len() <= PAD_MSG_BEFORE_HASH_BITS_LEN);
msg_bits.resize(PAD_MSG_BEFORE_HASH_BITS_LEN, false);
Expand All @@ -100,9 +100,40 @@ fn get_bits_le_fixed(fr: &Fr, size: usize) -> Vec<bool> {
}

pub fn rescue_hash_orders(msg: &[u8]) -> Vec<u8> {
assert_eq!(msg.len(), 178);
zkbenny marked this conversation as resolved.
Show resolved Hide resolved
let msg_bits = bytes_into_be_bits(msg);
let hash_fr = rescue_hash_fr(msg_bits);
let hash_bits = get_bits_le_fixed(&hash_fr, 248);
pack_bits_into_bytes_le(&hash_bits)
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_rescue_hash_tx_msg() {
let msg = [1u8, 2u8, 3u8, 4u8];
let hash = rescue_hash_tx_msg(&msg);

assert_eq!(
hash,
vec![
249, 154, 208, 123, 96, 89, 132, 235, 231, 63, 56, 200, 153, 131, 27, 183, 128, 71,
26, 245, 208, 120, 49, 246, 233, 72, 230, 84, 66, 150, 170, 27
]
);
}

#[test]
fn test_rescue_hash_orders() {
let msg = [1u8, 2, 3, 4, 5];
let hash = rescue_hash_orders(&msg);
assert_eq!(
hash,
vec![
88, 229, 220, 95, 31, 216, 185, 113, 100, 149, 78, 174, 140, 96, 206, 176, 152, 81,
237, 23, 246, 77, 252, 113, 151, 247, 40, 110, 136, 240, 36
]
);
}
}
8 changes: 4 additions & 4 deletions types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
ethers = "2.0.10"
ethers = "2.0"
hex = "0.4"
num = { version = "0.4.0", features = ["serde"] }
serde = "1.0.137"
serde_json = "1.0.0"
num = { version = "0.4", features = ["serde"] }
serde = "1.0"
serde_json = "1.0"
thiserror = "1.0"
validator = { version = "0.15", features = ["derive"] }
zklink_sdk_signers = { path = "../signers" }
Expand Down
54 changes: 54 additions & 0 deletions types/src/basic_types/bit_convert.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
pub struct BitConvert;

impl BitConvert {
/// Сonverts a set of bits to a set of bytes in direct order.
pub fn into_bytes(bits: Vec<bool>) -> Vec<u8> {
assert_eq!(bits.len() % 8, 0);
let mut message_bytes: Vec<u8> = vec![];

let byte_chunks = bits.chunks(8);
for byte_chunk in byte_chunks {
let mut byte = 0u8;
for (i, bit) in byte_chunk.iter().enumerate() {
if *bit {
byte |= 1 << i;
}
}
message_bytes.push(byte);
}

message_bytes
}

/// Сonverts a set of bits to a set of bytes in reverse order for each byte.
pub fn into_bytes_ordered(bits: Vec<bool>) -> Vec<u8> {
assert_eq!(bits.len() % 8, 0);
let mut message_bytes: Vec<u8> = vec![];

let byte_chunks = bits.chunks(8);
for byte_chunk in byte_chunks {
let mut byte = 0u8;
for (i, bit) in byte_chunk.iter().rev().enumerate() {
if *bit {
byte |= 1 << i;
}
}
message_bytes.push(byte);
}

message_bytes
}

/// Сonverts a set of Big Endian bytes to a set of bits.
pub fn from_be_bytes(bytes: &[u8]) -> Vec<bool> {
let mut bits = vec![];
for byte in bytes {
let mut temp = *byte;
for _ in 0..8 {
bits.push(temp & 0x80 == 0x80);
temp <<= 1;
}
}
bits
}
}
106 changes: 70 additions & 36 deletions types/src/basic_types/float_convert.rs
Original file line number Diff line number Diff line change
@@ -1,42 +1,7 @@
use crate::basic_types::bit_convert::BitConvert;
use crate::error::TypeError as Error;
use num::{BigUint, ToPrimitive};

pub struct BitConvert;

impl BitConvert {
/// Сonverts a set of bits to a set of bytes in reverse order for each byte.
#[allow(clippy::wrong_self_convention)]
pub fn into_bytes_ordered(bits: Vec<bool>) -> Vec<u8> {
assert_eq!(bits.len() % 8, 0);
let mut message_bytes: Vec<u8> = vec![];

let byte_chunks = bits.chunks(8);
for byte_chunk in byte_chunks {
let mut byte = 0u8;
for (i, bit) in byte_chunk.iter().rev().enumerate() {
if *bit {
byte |= 1 << i;
}
}
message_bytes.push(byte);
}

message_bytes
}

/// Сonverts a set of Big Endian bytes to a set of bits.
pub fn from_be_bytes(bytes: &[u8]) -> Vec<bool> {
let mut bits = vec![];
for byte in bytes {
let mut temp = *byte;
for _ in 0..8 {
bits.push(temp & 0x80 == 0x80);
temp <<= 1;
}
}
bits
}
}
/// Convert Uint to the floating-point and vice versa.
pub struct FloatConversions;

Expand All @@ -51,6 +16,17 @@ impl FloatConversions {
BitConvert::into_bytes_ordered(vec)
}

/// Packs a BigUint less than 2 ^ 128 to a floating-point number with an exponent base = 10 that is greater or equal to initial number.
/// Can lose accuracy with small parameters `exponent_len` and `mantissa_len`.
pub fn pack_up(number: &BigUint, exponent_len: usize, mantissa_len: usize) -> Vec<u8> {
let uint = number.to_u128().expect("Only u128 allowed");

let mut vec =
Self::to_float_up(uint, exponent_len, mantissa_len, 10).expect("packing error");
vec.reverse();
BitConvert::into_bytes_ordered(vec)
}

/// Unpacks a floating point number with the given parameters.
/// Returns `None` for numbers greater than 2 ^ 128.
pub fn unpack(data: &[u8], exponent_len: usize, mantissa_len: usize) -> Option<u128> {
Expand Down Expand Up @@ -131,6 +107,64 @@ impl FloatConversions {
}
};

// encode into bits. First bits of mantissa in LE order
let mut encoding = Vec::with_capacity(exponent_length + mantissa_length);

for i in 0..exponent_length {
if exponent & (1 << i) != 0 {
encoding.push(true);
} else {
encoding.push(false);
}
}

for i in 0..mantissa_length {
if mantissa & (1 << i) != 0 {
encoding.push(true);
} else {
encoding.push(false);
}
}

debug_assert_eq!(encoding.len(), exponent_length + mantissa_length);
Ok(encoding)
}

/// Packs a u128 to a floating-point number with the given parameters that is greater or equal to integer.
/// Can lose accuracy with small parameters `exponent_len` and `mantissa_len`.
#[allow(clippy::wrong_self_convention)]
pub fn to_float_up(
integer: u128,
exponent_length: usize,
mantissa_length: usize,
exponent_base: u32,
) -> Result<Vec<bool>, Error> {
let exponent_base = u128::from(exponent_base);

let max_power = (1 << exponent_length) - 1;

let max_exponent = exponent_base.saturating_pow(max_power);

let max_mantissa = (1u128 << mantissa_length) - 1;

if integer > (max_mantissa.saturating_mul(max_exponent)) {
return Err(Error::TooBigInteger);
}

// The algortihm is as follows: calculate minimal exponent
// such that integer <= max_mantissa * exponent_base ^ exponent,
// then mantissa is calculated as integer divided by exponent_base ^ exponent and rounded up
let mut exponent: usize = 0;
let mut exponent_temp: u128 = 1;
while integer > max_mantissa * exponent_temp {
exponent_temp *= exponent_base;
exponent += 1;
}
let mut mantissa = integer / exponent_temp;
if integer % exponent_temp != 0 {
mantissa += 1;
}

// encode into bits. First bits of mantissa in LE order

let mut encoding = Vec::with_capacity(exponent_length + mantissa_length);
Expand Down
Loading
Loading