Переглянути джерело

begin to add full darkfi smart contract functionality

x 3 роки тому
батько
коміт
66198e60a6

+ 97 - 22
example/smart-contract/src/lib.rs

@@ -1,43 +1,90 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2022 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
 use darkfi_sdk::{
     crypto::Nullifier,
-    entrypoint,
+    initialize, entrypoint, update_state,
     error::{ContractError, ContractResult},
     msg,
     pasta::pallas,
-    state::nullifier_exists,
+    state::{set_update, nullifier_exists},
 };
-use darkfi_serial::{deserialize, SerialDecodable, SerialEncodable};
+use darkfi_serial::{deserialize, serialize, SerialDecodable, SerialEncodable};
+
+/// Available functions for this contract.
+/// We identify them with the first byte passed in through the payload.
+#[repr(u8)]
+pub enum Function {
+    Foo = 0x00,
+    Bar = 0x01,
+}
+
+impl From<u8> for Function {
+    fn from(b: u8) -> Self {
+        match b {
+            0x00 => Self::Foo,
+            0x01 => Self::Bar,
+            _ => panic!("Invalid function ID: {:#04x?}", b),
+        }
+    }
+}
 
 // An example of deserializing the payload into a struct
 #[derive(SerialEncodable, SerialDecodable)]
-pub struct Args {
+pub struct FooArgs {
     pub a: u64,
     pub b: u64,
 }
 
+#[derive(SerialEncodable, SerialDecodable)]
+pub struct BarArgs {
+    pub x: u32,
+}
+
+#[derive(SerialEncodable, SerialDecodable)]
+pub struct FooUpdate {
+    pub name: String,
+    pub y: u32
+}
+
+initialize!(init_contract);
+fn init_contract() -> ContractResult {
+    // db_exists(field_name) -> bool
+    // db_delete(field_name)
+    //     panics if NAME does not exist
+    //     abort deployment
+    // db_create(field_name)
+    //
+    // internal_db_name = blake3_hash(contract_id, field_name)
+    msg!("init!");
+    Ok(())
+}
+
 // This is the main entrypoint function where the payload is fed.
 // Through here, you can branch out into different functions inside
 // this library.
 entrypoint!(process_instruction);
 fn process_instruction(ix: &[u8]) -> ContractResult {
+    match Function::from(ix[0]) {
+        Function::Foo => {
+            let tx_data = &ix[1..];
+            // ...
+            let args: FooArgs = deserialize(tx_data)?;
+            // ...
+            let update = FooUpdate {
+                name: "john_doe".to_string(),
+                y: 110
+            };
+
+            let mut update_data = vec![Function::Foo as u8];
+            update_data.extend_from_slice(&serialize(&update));
+            set_update(&update_data)?;
+            msg!("update is set!");
+        }
+        Function::Bar => {
+            let tx_data = &ix[1..];
+            // ...
+            let args: BarArgs = deserialize(tx_data)?;
+        }
+    }
+    /*
     msg!("Hello from the VM runtime!");
     // Deserialize the payload into `Args`.
     let args: Args = deserialize(ix)?;
@@ -62,7 +109,35 @@ fn process_instruction(ix: &[u8]) -> ContractResult {
     } else {
         msg!("Nullifier doesn't exist");
     }
+    */
+
+    Ok(())
+}
+
+update_state!(process_update);
+fn process_update() -> ContractResult {
+    msg!("Make update!");
+
+    /*
+    let (func_id, update_data) = get_update()?;
+
+    match Function::from(func_id) {
+        Function::Foo => {
+            let update: FooUpdate = deserialize(update_data)?;
+            // update.apply()
+        }
+        _ => unreachable!()
+    };
+    */
 
     Ok(())
 }
 
+//fn state_transition() -> Result<StateUpdate> {
+//    // read only
+//}
+//
+//fn apply(update) {
+//    // writes happen here
+//}
+

+ 21 - 5
example/smart-contract/tests/runtime.rs

@@ -17,13 +17,14 @@
  */
 
 use darkfi::{
+    crypto::contract_id::ContractId,
     runtime::{util::serialize_payload, vm_runtime::Runtime},
     Result,
 };
 use darkfi_sdk::{crypto::nullifier::Nullifier, pasta::pallas};
 use darkfi_serial::serialize;
 
-use smart_contract::Args;
+use smart_contract::FooArgs;
 
 #[test]
 fn run_contract() -> Result<()> {
@@ -48,16 +49,31 @@ fn run_contract() -> Result<()> {
     // Load the wasm binary into memory and create an execution runtime
     // ================================================================
     let wasm_bytes = std::fs::read("contract.wasm")?;
-    let mut runtime = Runtime::new(&wasm_bytes)?;
+    let contract_id = ContractId::new(pallas::Base::from(1));
+    let mut runtime = Runtime::new(&wasm_bytes, contract_id)?;
+
+    runtime.deploy()?;
 
     // =============================================
     // Build some kind of payload to show an example
     // =============================================
-    let args = Args { a: 777, b: 666 };
-    let payload = serialize(&args);
+    let args = FooArgs { a: 777, b: 666 };
+    // Prepend the func id
+    let mut payload = vec![0x00];
+    payload.extend_from_slice(&serialize(&args));
 
     // ============================================================
     // Serialize the payload into the runtime format and execute it
     // ============================================================
-    runtime.run(&serialize_payload(&payload))
+    //let update = runtime.exec(&serialize_payload(&payload))?;
+
+    //runtime.apply(update);
+    //Ok(())
+
+    //runtime.exec(&serialize_payload(&payload))?;
+
+    //runtime.apply()?;
+
+    Ok(())
 }
+

+ 2 - 1
src/consensus/coins.rs

@@ -255,7 +255,8 @@ fn create_leadcoin(
     let c_cm_coordinates = c_cm.to_affine().coordinates().unwrap();
     let c_cm_msg = [*c_cm_coordinates.x(), *c_cm_coordinates.y()];
     let c_cm_base: pallas::Base =
-        poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<2>, 3, 2>::init().hash(c_cm_msg);
+        poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<2>, 3, 2>::init()
+            .hash(c_cm_msg);
     let c_cm_node = MerkleNode::from(c_cm_base);
     tree_cm.append(&c_cm_node.clone());
     let leaf_position = tree_cm.witness();

+ 10 - 0
src/crypto/contract_id.rs

@@ -29,6 +29,16 @@ use super::{
 #[derive(Debug, Copy, Clone, SerialEncodable, SerialDecodable)]
 pub struct ContractId(pallas::Base);
 
+impl ContractId {
+    pub fn new(contract_id: pallas::Base) -> Self {
+        Self(contract_id)
+    }
+
+    pub fn inner(&self) -> pallas::Base {
+        self.0
+    }
+}
+
 /// Derive a ContractId given a secret deploy key.
 pub fn derive_contract_id(deploy_key: SecretKey) -> ContractId {
     let public_key = PublicKey::from_secret(deploy_key);

+ 4 - 1
src/error.rs

@@ -294,6 +294,10 @@ pub enum Error {
     #[error("wasm runtime out of memory")]
     WasmerOomError(String),
 
+    #[cfg(feature = "wasm-runtime")]
+    #[error("contract initialize error")]
+    ContractInitError(u64),
+
     #[cfg(feature = "wasm-runtime")]
     #[error("contract execution error")]
     ContractExecError(u64),
@@ -590,4 +594,3 @@ impl From<wasmer::MemoryError> for Error {
         Self::WasmerOomError(err.to_string())
     }
 }
-

+ 76 - 4
src/runtime/chain_state.rs

@@ -18,14 +18,86 @@
 
 use darkfi_sdk::crypto::{MerkleNode, Nullifier};
 use log::{debug, error};
-use wasmer::FunctionEnvMut;
+use wasmer::{AsStoreRef, FunctionEnvMut, WasmPtr};
 
-use super::{memory::MemoryManipulation, vm_runtime::Env};
+use super::{
+    memory::MemoryManipulation,
+    vm_runtime::{ContractSection, Env},
+};
 use crate::node::state::ProgramState;
 
+pub(crate) fn set_update(mut ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, len: u32) -> i32 {
+    let env = ctx.data();
+    match env.contract_section {
+        ContractSection::Exec => {
+            let memory_view = env.memory_view(&ctx);
+
+            // FIXME: make me preettty!
+            let slice = ptr.slice(&memory_view, len);
+            if slice.is_err() {
+                return -2;
+            }
+            let slice = slice.unwrap();
+
+            // FIXME: make me double pretty
+            // before:
+            //let update_data = slice.read_to_vec();
+            //if update_data.is_err() {
+            //    return -2;
+            //}
+            //let update_data = update_data.unwrap();
+
+            // after:
+            let Ok(update_data) = slice.read_to_vec() else {
+                return -2;
+            };
+            //
+
+            assert!(env.contract_update.take().is_none());
+            let func_id = update_data[0];
+            let update_data = &update_data[1..];
+            env.contract_update.set(Some((func_id, update_data.to_vec())));
+            0
+        }
+        _ => {
+            -1
+        }
+    }
+}
+
+pub(crate) fn get_update(mut ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, len: u32) -> i32 {
+    let env = ctx.data();
+    match env.contract_section {
+        ContractSection::Update => {
+           let memory_view = env.memory_view(&ctx);
+
+
+
+           0
+
+        }
+        _ => { -1 }
+    }
+}
+
 /// Try to read a `Nullifier` from the given pointer and check if it's
 /// an existing nullifier in the blockchain state machine.
-pub fn nullifier_exists(mut env: FunctionEnvMut<Env>, ptr: u32, len: u32) -> i32 {
+pub fn nullifier_exists(mut ctx: FunctionEnvMut<Env>, ptr: u32, len: u32) -> i32 {
+    let env = ctx.data();
+    match env.contract_section {
+        ContractSection::Null => {
+            unreachable!();
+        }
+        ContractSection::Deploy => {
+            debug!(target: "nullifier_exists", "deploy!!!");
+        }
+        ContractSection::Exec => {
+            debug!(target: "nullifier_exists", "exec!!!");
+        }
+        ContractSection::Update => {
+            debug!(target: "nullifier_exists", "apply!!!");
+        }
+    }
     /*
     if let Some(bytes) = env.memory.get_ref().unwrap().read(ptr, len as usize) {
         debug!(target: "wasm_runtime::nullifier_exists", "Read bytes: {:?}", bytes);
@@ -55,7 +127,7 @@ pub fn nullifier_exists(mut env: FunctionEnvMut<Env>, ptr: u32, len: u32) -> i32
 
 /// Try to read a `MerkleNode` from the given pointer and check if it's
 /// a valid Merkle root in the chain's Merkle tree.
-pub fn is_valid_merkle(mut env: FunctionEnvMut<Env>, ptr: u32, len: u32) -> i32 {
+pub fn is_valid_merkle(mut ctx: FunctionEnvMut<Env>, ptr: u32, len: u32) -> i32 {
     /*
     if let Some(bytes) = env.memory.get_ref().unwrap().read(ptr, len as usize) {
         debug!(target: "wasm_runtime::is_valid_merkle", "Read bytes: {:?}", bytes);

+ 112 - 15
src/runtime/vm_runtime.rs

@@ -17,7 +17,7 @@
  */
 
 use std::{
-    cell::RefCell,
+    cell::{Cell, RefCell},
     sync::{Arc, Mutex},
 };
 
@@ -34,21 +34,36 @@ use wasmer_middlewares::{
 };
 
 use super::{
-    chain_state::{is_valid_merkle, nullifier_exists},
+    chain_state::{set_update, is_valid_merkle, nullifier_exists},
     memory::MemoryManipulation,
     util::drk_log,
 };
-use crate::{Error, Result};
+use crate::{crypto::contract_id::ContractId, Error, Result};
 
 /// Name of the wasm linear memory in our guest module
 const MEMORY: &str = "memory";
+/// Hardcoded setup function of a contract
+pub const INITIALIZE: &str = "__initialize";
 /// Hardcoded entrypoint function of a contract
-pub const ENTRYPOINT: &str = "entrypoint";
+pub const ENTRYPOINT: &str = "__entrypoint";
+/// Hardcoded apply function of a contract
+pub const UPDATE: &str = "__update";
 /// Gas limit for a contract
 const GAS_LIMIT: u64 = 200000;
 
+pub enum ContractSection {
+    Null,
+    Deploy,
+    Exec,
+    Update,
+}
+
 /// The wasm vm runtime instantiated for every smart contract that runs.
 pub struct Env {
+    pub contract_id: ContractId,
+    pub contract_section: ContractSection,
+    pub contract_update: Cell<Option<(u8, Vec<u8>)>>,
+    //pub func_id:
     /// Logs produced by the contract
     pub logs: RefCell<Vec<String>>,
     /// Direct memory access to the VM
@@ -73,14 +88,6 @@ impl Env {
     }
 }
 
-/// The result of the VM execution
-pub struct ExecutionResult {
-    /// The exit code returned by the wasm program
-    pub exitcode: u8,
-    /// Logs written from the wasm program
-    pub logs: Vec<String>,
-}
-
 pub struct Runtime {
     pub instance: Instance,
     pub store: Store,
@@ -89,7 +96,7 @@ pub struct Runtime {
 
 impl Runtime {
     /// Create a new wasm runtime instance that contains the given wasm module.
-    pub fn new(wasm_bytes: &[u8]) -> Result<Self> {
+    pub fn new(wasm_bytes: &[u8], contract_id: ContractId) -> Result<Self> {
         info!(target: "warm_runtime::new", "Instantiating a new runtime");
         // This function will be called for each `Operator` encountered during
         // the wasm module execution. It should return the cost of the operator
@@ -121,7 +128,16 @@ impl Runtime {
         debug!(target: "wasm_runtime::new", "Importing functions");
         let logs = RefCell::new(vec![]);
 
-        let ctx = FunctionEnv::new(&mut store, Env { logs, memory: None });
+        let ctx = FunctionEnv::new(
+            &mut store,
+            Env {
+                contract_id,
+                contract_section: ContractSection::Null,
+                contract_update: Cell::new(None),
+                logs,
+                memory: None,
+            },
+        );
 
         let imports = imports! {
             "env" => {
@@ -142,6 +158,12 @@ impl Runtime {
                     &ctx,
                     is_valid_merkle,
                 ),
+
+                "set_update_" => Function::new_typed_with_env(
+                    &mut store,
+                    &ctx,
+                    set_update,
+                ),
             }
         };
 
@@ -154,8 +176,47 @@ impl Runtime {
         Ok(Self { instance, store, ctx })
     }
 
+    pub fn deploy(&mut self) -> Result<()> {
+        let mut env_mut = self.ctx.as_mut(&mut self.store);
+        env_mut.contract_section = ContractSection::Deploy;
+
+        debug!(target: "wasm_runtime::run", "Getting initialize function");
+        let entrypoint = self.instance.exports.get_function(INITIALIZE)?;
+
+        debug!(target: "wasm_runtime::run", "Executing wasm");
+        let ret = match entrypoint.call(&mut self.store, &[]) {
+            Ok(retvals) => {
+                self.print_logs();
+                debug!(target: "wasm_runtime::run", "{}", self.gas_info());
+                retvals
+            }
+            Err(e) => {
+                self.print_logs();
+                debug!(target: "wasm_runtime::run", "{}", self.gas_info());
+                // WasmerRuntimeError panics are handled here. Return from run() immediately.
+                return Err(e.into())
+            }
+        };
+
+        debug!(target: "wasm_runtime::run", "wasm executed successfully");
+        debug!(target: "wasm_runtime::run", "Contract returned: {:?}", ret[0]);
+
+        let retval = match ret[0] {
+            Value::I64(v) => v as u64,
+            _ => unreachable!(),
+        };
+
+        match retval {
+            entrypoint::SUCCESS => Ok(()),
+            _ => Err(Error::ContractInitError(retval)),
+        }
+    }
+
     /// Run the hardcoded `ENTRYPOINT` function with the given payload as input.
-    pub fn run(&mut self, payload: &[u8]) -> Result<()> {
+    pub fn exec(&mut self, payload: &[u8]) -> Result<()> {
+        let mut env_mut = self.ctx.as_mut(&mut self.store);
+        env_mut.contract_section = ContractSection::Exec;
+
         let pages_required = payload.len() / WASM_PAGE_SIZE + 1;
         self.set_memory_page_size(pages_required as u32)?;
 
@@ -194,6 +255,42 @@ impl Runtime {
         }
     }
 
+    pub fn apply(&mut self) -> Result<()> {
+        let mut env_mut = self.ctx.as_mut(&mut self.store);
+        env_mut.contract_section = ContractSection::Update;
+
+        debug!(target: "wasm_runtime::run", "Getting initialize function");
+        let entrypoint = self.instance.exports.get_function(INITIALIZE)?;
+
+        debug!(target: "wasm_runtime::run", "Executing wasm");
+        let ret = match entrypoint.call(&mut self.store, &[]) {
+            Ok(retvals) => {
+                self.print_logs();
+                debug!(target: "wasm_runtime::run", "{}", self.gas_info());
+                retvals
+            }
+            Err(e) => {
+                self.print_logs();
+                debug!(target: "wasm_runtime::run", "{}", self.gas_info());
+                // WasmerRuntimeError panics are handled here. Return from run() immediately.
+                return Err(e.into())
+            }
+        };
+
+        debug!(target: "wasm_runtime::run", "wasm executed successfully");
+        debug!(target: "wasm_runtime::run", "Contract returned: {:?}", ret[0]);
+
+        let retval = match ret[0] {
+            Value::I64(v) => v as u64,
+            _ => unreachable!(),
+        };
+
+        match retval {
+            entrypoint::SUCCESS => Ok(()),
+            _ => Err(Error::ContractInitError(retval)),
+        }
+    }
+
     fn print_logs(&self) {
         let logs = self.ctx.as_ref(&self.store).logs.borrow();
         for msg in logs.iter() {

+ 29 - 1
src/sdk/src/entrypoint.rs

@@ -21,6 +21,20 @@ use std::{mem::size_of, slice::from_raw_parts};
 /// Success exit code for a contract
 pub const SUCCESS: u64 = 0;
 
+#[macro_export]
+macro_rules! initialize {
+    ($process_init:ident) => {
+        /// # Safety
+        #[no_mangle]
+        pub unsafe extern "C" fn __initialize() -> u64 {
+            match $process_init() {
+                Ok(()) => $crate::entrypoint::SUCCESS,
+                Err(e) => e.into(),
+            }
+        }
+    };
+}
+
 /// This macro is used to flag the contract entrypoint function.
 /// All contracts must provide such a function and accept a payload.
 ///
@@ -31,7 +45,7 @@ macro_rules! entrypoint {
     ($process_instruction:ident) => {
         /// # Safety
         #[no_mangle]
-        pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64 {
+        pub unsafe extern "C" fn __entrypoint(input: *mut u8) -> u64 {
             let instruction_data = $crate::entrypoint::deserialize(input);
 
             match $process_instruction(&instruction_data) {
@@ -42,6 +56,20 @@ macro_rules! entrypoint {
     };
 }
 
+#[macro_export]
+macro_rules! update_state {
+    ($process_update:ident) => {
+        /// # Safety
+        #[no_mangle]
+        pub unsafe extern "C" fn __update() -> u64 {
+            match $process_update() {
+                Ok(()) => $crate::entrypoint::SUCCESS,
+                Err(e) => e.into(),
+            }
+        }
+    };
+}
+
 /// Deserialize a given payload in `entrypoint`
 /// # Safety
 pub unsafe fn deserialize<'a>(input: *mut u8) -> &'a [u8] {

+ 9 - 3
src/sdk/src/error.rs

@@ -35,6 +35,9 @@ pub enum ContractError {
     #[error("IO error: {0}")]
     IoError(String),
 
+    #[error("Error setting update")]
+    SetUpdateError,
+
     #[error("Error checking if nullifier exists")]
     NullifierExistCheck,
 
@@ -52,15 +55,17 @@ macro_rules! to_builtin {
 
 pub const CUSTOM_ZERO: u64 = to_builtin!(1);
 pub const INTERNAL_ERROR: u64 = to_builtin!(2);
-pub const IO_ERROR: u64 = to_builtin!(3);
-pub const NULLIFIER_EXIST_CHECK: u64 = to_builtin!(4);
-pub const VALID_MERKLE_CHECK: u64 = to_builtin!(5);
+pub const SET_UPDATE_ERROR: u64 = to_builtin!(3);
+pub const IO_ERROR: u64 = to_builtin!(4);
+pub const NULLIFIER_EXIST_CHECK: u64 = to_builtin!(5);
+pub const VALID_MERKLE_CHECK: u64 = to_builtin!(6);
 
 impl From<ContractError> for u64 {
     fn from(err: ContractError) -> Self {
         match err {
             ContractError::Internal => INTERNAL_ERROR,
             ContractError::IoError(_) => IO_ERROR,
+            ContractError::SetUpdateError => SET_UPDATE_ERROR,
             ContractError::NullifierExistCheck => NULLIFIER_EXIST_CHECK,
             ContractError::ValidMerkleCheck => VALID_MERKLE_CHECK,
             ContractError::Custom(error) => {
@@ -79,6 +84,7 @@ impl From<u64> for ContractError {
         match error {
             CUSTOM_ZERO => Self::Custom(0),
             INTERNAL_ERROR => Self::Internal,
+            SET_UPDATE_ERROR => Self::SetUpdateError,
             IO_ERROR => Self::IoError("Unknown".to_string()),
             NULLIFIER_EXIST_CHECK => Self::NullifierExistCheck,
             VALID_MERKLE_CHECK => Self::ValidMerkleCheck,

+ 26 - 2
src/sdk/src/state.rs

@@ -21,8 +21,30 @@ use super::{
     error::{ContractError, ContractResult},
 };
 
-pub trait Verification {
-    fn verify(&self) -> ContractResult;
+pub fn set_update(update_data: &[u8]) -> Result<(), ContractError> {
+    #[cfg(target_arch = "wasm32")]
+    unsafe {
+        return match set_update_(update_data.as_ptr(), update_data.len() as u32) {
+            0 => Ok(()),
+            -1 => Err(ContractError::SetUpdateError),
+            _ => unreachable!(),
+        }
+    }
+
+    #[cfg(not(target_arch = "wasm32"))]
+    unimplemented!();
+}
+
+pub fn get_update() -> Result<(u8, Vec<u8>), ContractError> {
+    #[cfg(target_arch = "wasm32")]
+    // get_update_ needs to take a buffer?
+    // get pointer for contract_update
+    // piece back into (u8, Vec<u8>)
+    // return
+    return Ok((0, vec![]));
+
+    #[cfg(not(target_arch = "wasm32"))]
+    unimplemented!();
 }
 
 pub fn nullifier_exists(nullifier: &Nullifier) -> Result<bool, ContractError> {
@@ -63,6 +85,8 @@ pub fn is_valid_merkle(merkle_root: &MerkleNode) -> Result<bool, ContractError>
 
 #[cfg(target_arch = "wasm32")]
 extern "C" {
+    fn get_update_() -> i32;
+    fn set_update_(ptr: *const u8, len: u32) -> i32;
     fn nullifier_exists_(ptr: *const u8, len: u32) -> i32;
     fn is_valid_merkle_(ptr: *const u8, len: u32) -> i32;
 }

+ 5 - 17
src/zk/circuit/lead_contract.rs

@@ -60,7 +60,6 @@ use crate::zk::{
     },
 };
 
-
 /// Public input offset for the lead coin C2 nonce
 const LEADCOIN_C2_NONCE_OFFSET: usize = 0;
 /// Public input offset for lead coin public key X coordinate
@@ -449,8 +448,6 @@ impl Circuit<pallas::Base> for LeadContract {
             coin_pk_commit_v.mul(layouter.namespace(|| "coin_1sk * NullifierK"), coin1_sk)?
         };
 
-
-
         // Coin `c1` serial number:
         // sn=PRF_{root_sk}(nonce)
         // Coin's serial number is derived from coin nonce (sampled at random)
@@ -469,8 +466,6 @@ impl Circuit<pallas::Base> for LeadContract {
             poseidon_output.into()
         };
 
-
-
         // ==============================
         // Commitment to the staking coin
         // ==============================
@@ -536,8 +531,6 @@ impl Circuit<pallas::Base> for LeadContract {
             coin1_commit_hash,
         )?;
 
-
-
         // ===========================
         // Derivation of coin2's nonce
         // ===========================
@@ -555,7 +548,6 @@ impl Circuit<pallas::Base> for LeadContract {
             poseidon_output.into()
         };
 
-
         // ================
         // Coin2 commitment
         // ================
@@ -599,8 +591,6 @@ impl Circuit<pallas::Base> for LeadContract {
             &coin2_commitment_r,
         )?;
 
-
-
         // ==================================
         // lhs of the leader election lottery
         // ==================================
@@ -654,13 +644,11 @@ impl Circuit<pallas::Base> for LeadContract {
                 layouter.namespace(|| "mau_rho scalar"),
                 self.mau_rho,
             )?;
-            let rho_commit_r =
-                FixedPoint::from_inner(ecc_chip.clone(), ValueCommitR);
+            let rho_commit_r = FixedPoint::from_inner(ecc_chip.clone(), ValueCommitR);
             rho_commit_r.mul(layouter.namespace(|| "coin serial number commit R"), mau_rho)?
         };
         let rho_commit = lottery_commit_v.add(layouter.namespace(|| "nonce commit"), &rho_cm)?;
 
-
         // Calculate term1 and term2 for the lottery
         let term1 = arith_chip.mul(
             layouter.namespace(|| "term1 = sigma1 * coin1_value"),
@@ -682,7 +670,6 @@ impl Circuit<pallas::Base> for LeadContract {
         let target =
             arith_chip.add(layouter.namespace(|| "target = term1 + term2"), &term1, &term2)?;
 
-
         // Constrain y < target
         lessthan_chip.copy_less_than(
             layouter.namespace(|| "y < target"),
@@ -692,7 +679,6 @@ impl Circuit<pallas::Base> for LeadContract {
             true,
         )?;
 
-
         // Constrain derived `sn_commit` to be equal to witnessed `coin1_serial`.
         layouter.assign_region(
             || "sn_commit equality",
@@ -703,7 +689,8 @@ impl Circuit<pallas::Base> for LeadContract {
         );
 
         // Constrain equality between witnessed and derived commitment
-        coin2_commitment.constrain_equal(layouter.namespace(|| "coin2_commit equality"), &coin2_commit)?;
+        coin2_commitment
+            .constrain_equal(layouter.namespace(|| "coin2_commit equality"), &coin2_commit)?;
 
         // Constrain derived rho_commit to witnessed rho
         rho_commit.constrain_equal(layouter.namespace(|| "rho equality"), &rho)?;
@@ -754,7 +741,8 @@ mod tests {
         let root = root.titled("Lead Circuit Layout", ("sans-serif", 60)).unwrap();
         CircuitLayout::default()
             //.view_width(0..10)
-            .render(k, &circuit, &root).unwrap();
+            .render(k, &circuit, &root)
+            .unwrap();
 
         Ok(())
     }