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

Read/Write register values in ErgoBox/ErgoBoxCandidate #116

Merged
merged 7 commits into from
Oct 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion bindings/ergo-lib-wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,5 @@ default-features = false
features = ["std"]

[package.metadata.wasm-pack.profile.release]
wasm-opt = ["-O", "--enable-mutable-globals"]
# wasm-opt = ["-O", "--enable-mutable-globals"]
wasm-opt = false
12 changes: 12 additions & 0 deletions bindings/ergo-lib-wasm/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,15 @@ impl Constant {
.map_err(|e| JsValue::from_str(&format! {"{:?}", e}))
}
}

impl From<ergo_lib::ast::Constant> for Constant {
fn from(c: ergo_lib::ast::Constant) -> Self {
Constant(c)
}
}

impl From<Constant> for ergo_lib::ast::Constant {
fn from(c: Constant) -> Self {
c.0
}
}
70 changes: 69 additions & 1 deletion bindings/ergo-lib-wasm/src/ergo_box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use chain::ergo_box::register::NonMandatoryRegisters;
use ergo_lib::chain;
use wasm_bindgen::prelude::*;

use crate::ast::Constant;
use crate::{contract::Contract, transaction::TxId};

pub mod box_builder;
Expand All @@ -32,7 +33,16 @@ pub mod box_builder;
pub struct ErgoBoxCandidate(chain::ergo_box::ErgoBoxCandidate);

#[wasm_bindgen]
impl ErgoBoxCandidate {}
impl ErgoBoxCandidate {
/// Returns value (ErgoTree constant) stored in the register or None if the register is empty
pub fn register_value(&self, register_id: NonMandatoryRegisterId) -> Option<Constant> {
self.0
.additional_registers
.get(register_id.into())
.cloned()
.map(Constant::from)
}
}

impl Into<chain::ergo_box::ErgoBoxCandidate> for ErgoBoxCandidate {
fn into(self) -> chain::ergo_box::ErgoBoxCandidate {
Expand Down Expand Up @@ -76,6 +86,15 @@ impl ErgoBox {
ErgoBox(b)
}

/// Returns value (ErgoTree constant) stored in the register or None if the register is empty
pub fn register_value(&self, register_id: NonMandatoryRegisterId) -> Option<Constant> {
self.0
.additional_registers
.get(register_id.into())
.cloned()
.map(Constant::from)
}

// JSON representation
// pub fn to_json(&self) -> Result<JsValue, JsValue> {
// JsValue::from_serde(&self.0).map_err(|e| JsValue::from_str(&format!("{}", e)))
Expand Down Expand Up @@ -122,3 +141,52 @@ impl From<chain::ergo_box::box_value::BoxValue> for BoxValue {
BoxValue(v)
}
}

/// newtype for box registers R4 - R9
#[wasm_bindgen]
#[repr(u8)]
#[derive(PartialEq, Eq, Clone, Debug)]
pub enum NonMandatoryRegisterId {
/// id for R4 register
R4 = 4,
/// id for R5 register
R5 = 5,
/// id for R6 register
R6 = 6,
/// id for R7 register
R7 = 7,
/// id for R8 register
R8 = 8,
/// id for R9 register
R9 = 9,
}

impl NonMandatoryRegisterId {}

impl From<NonMandatoryRegisterId> for chain::ergo_box::register::NonMandatoryRegisterId {
fn from(v: NonMandatoryRegisterId) -> Self {
use chain::ergo_box::register::NonMandatoryRegisterId::*;
match v {
NonMandatoryRegisterId::R4 => R4,
NonMandatoryRegisterId::R5 => R5,
NonMandatoryRegisterId::R6 => R6,
NonMandatoryRegisterId::R7 => R7,
NonMandatoryRegisterId::R8 => R8,
NonMandatoryRegisterId::R9 => R9,
}
}
}

impl From<chain::ergo_box::register::NonMandatoryRegisterId> for NonMandatoryRegisterId {
fn from(v: chain::ergo_box::register::NonMandatoryRegisterId) -> Self {
use NonMandatoryRegisterId::*;
match v {
chain::ergo_box::register::NonMandatoryRegisterId::R4 => R4,
chain::ergo_box::register::NonMandatoryRegisterId::R5 => R5,
chain::ergo_box::register::NonMandatoryRegisterId::R6 => R6,
chain::ergo_box::register::NonMandatoryRegisterId::R7 => R7,
chain::ergo_box::register::NonMandatoryRegisterId::R8 => R8,
chain::ergo_box::register::NonMandatoryRegisterId::R9 => R9,
}
}
}
42 changes: 34 additions & 8 deletions bindings/ergo-lib-wasm/src/ergo_box/box_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
use ergo_lib::chain;
use wasm_bindgen::prelude::*;

use crate::ast::Constant;
use crate::contract::Contract;

use super::BoxValue;
use super::ErgoBoxCandidate;
use super::NonMandatoryRegisterId;

/// ErgoBoxCandidate builder
#[wasm_bindgen]
Expand All @@ -29,8 +31,8 @@ impl ErgoBoxCandidateBuilder {
}

/// Set minimal value (per byte of the serialized box size)
pub fn set_min_box_value_per_byte(self, new_min_value_per_byte: u32) -> Self {
ErgoBoxCandidateBuilder(self.0.set_min_box_value_per_byte(new_min_value_per_byte))
pub fn set_min_box_value_per_byte(&mut self, new_min_value_per_byte: u32) {
self.0.set_min_box_value_per_byte(new_min_value_per_byte);
}

/// Get minimal value (per byte of the serialized box size)
Expand All @@ -39,8 +41,8 @@ impl ErgoBoxCandidateBuilder {
}

/// Set new box value
pub fn set_value(self, new_value: BoxValue) -> Self {
ErgoBoxCandidateBuilder(self.0.set_value(new_value.into()))
pub fn set_value(&mut self, new_value: BoxValue) {
self.0.set_value(new_value.into());
}

/// Get box value
Expand All @@ -49,13 +51,37 @@ impl ErgoBoxCandidateBuilder {
}

/// Calculate serialized box size(in bytes)
pub fn calc_box_size_bytes(&self) -> usize {
self.0.calc_box_size_bytes()
pub fn calc_box_size_bytes(&self) -> Result<usize, JsValue> {
self.0
.calc_box_size_bytes()
.map_err(|e| JsValue::from_str(&format!("{}", e)))
}

/// Calculate minimal box value for the current box serialized size(in bytes)
pub fn calc_min_box_value(&self) -> BoxValue {
self.0.calc_min_box_value().into()
pub fn calc_min_box_value(&self) -> Result<BoxValue, JsValue> {
self.0
.calc_min_box_value()
.map(BoxValue::from)
.map_err(|e| JsValue::from_str(&format!("{}", e)))
}

/// Set register with a given id (R4-R9) to the given value
pub fn set_register_value(&mut self, register_id: NonMandatoryRegisterId, value: &Constant) {
self.0
.set_register_value(register_id.into(), value.clone().into());
}

/// Returns register value for the given register id (R4-R9), or None if the register is empty
pub fn register_value(&self, register_id: NonMandatoryRegisterId) -> Option<Constant> {
self.0
.register_value(&register_id.into())
.cloned()
.map(Constant::from)
}

/// Delete register value(make register empty) for the given register id (R4-R9)
pub fn delete_register_value(&mut self, register_id: NonMandatoryRegisterId) {
self.0.delete_register_value(&register_id.into());
}

/// Build the box candidate
Expand Down
4 changes: 2 additions & 2 deletions bindings/ergo-lib-wasm/src/tx_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ impl TxBuilder {
}

/// Set transaction's data inputs
pub fn set_data_inputs(self, data_inputs: &DataInputs) -> TxBuilder {
TxBuilder(self.0.set_data_inputs(data_inputs.into()))
pub fn set_data_inputs(&mut self, data_inputs: &DataInputs) {
self.0.set_data_inputs(data_inputs.into())
}

/// Build the unsigned transaction
Expand Down
36 changes: 36 additions & 0 deletions bindings/ergo-lib-wasm/tests/test_box_builder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { expect, assert } from 'chai';

import {
Address, Wallet, ErgoBox, ErgoBoxCandidateBuilder, Contract,
ErgoBoxes, ErgoBoxCandidates,
ErgoStateContext, TxBuilder, BoxValue, BoxSelector, SecretKey, TxId, DataInputs, NonMandatoryRegisterId, Constant
} from '../pkg/ergo_lib_wasm';

const recipient = Address.from_testnet_str('3WvsT2Gm4EpsM9Pg18PdY6XyhNNMqXDsvJTbbf6ihLvAmSb7u5RN');
const contract = Contract.pay_to_address(recipient);

it('ErgoBoxCandidateBuilder test', async () => {
const b = new ErgoBoxCandidateBuilder(BoxValue.from_u32(10000000), contract, 0).build();
assert(b != null);
});

it('ErgoBoxCandidateBuilder set register value test', async () => {
let builder = new ErgoBoxCandidateBuilder(BoxValue.from_u32(10000000), contract, 0);
assert(builder.register_value(NonMandatoryRegisterId.R4) == null);
const c = Constant.from_i32(1);
builder.set_register_value(NonMandatoryRegisterId.R4, c);
assert(builder.register_value(NonMandatoryRegisterId.R4).to_i32() == c.to_i32());
const b = builder.build();
assert(b.register_value(NonMandatoryRegisterId.R4).to_i32 = c.to_i32);
});

it('ErgoBoxCandidateBuilder delete register value test', async () => {
let builder = new ErgoBoxCandidateBuilder(BoxValue.from_u32(10000000), contract, 0);
const c = Constant.from_i32(1);
builder.set_register_value(NonMandatoryRegisterId.R4, c);
assert(builder.register_value(NonMandatoryRegisterId.R4).to_i32() == c.to_i32());
builder.delete_register_value(NonMandatoryRegisterId.R4);
assert(builder.register_value(NonMandatoryRegisterId.R4) == null);
const b = builder.build();
assert(b.register_value(NonMandatoryRegisterId.R4) == null);
});
7 changes: 3 additions & 4 deletions bindings/ergo-lib-wasm/tests/test_transaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { expect, assert } from 'chai';
import {
Address, Wallet, ErgoBox, ErgoBoxCandidateBuilder, Contract,
ErgoBoxes, ErgoBoxCandidates,
ErgoStateContext, TxBuilder, BoxValue, UnsignedTransaction, BoxSelector, SecretKey, TxId, DataInputs
ErgoStateContext, TxBuilder, BoxValue, BoxSelector, SecretKey, TxId, DataInputs
} from '../pkg/ergo_lib_wasm';

it('TxBuilder test', async () => {
Expand All @@ -27,13 +27,12 @@ it('TxBuilder test', async () => {
const change_address = Address.from_testnet_str('3WvsT2Gm4EpsM9Pg18PdY6XyhNNMqXDsvJTbbf6ihLvAmSb7u5RN');
const min_change_value = BoxValue.SAFE_USER_MIN();
const data_inputs = new DataInputs();
const tx_builder = TxBuilder.new(BoxSelector.SelectAll, unspent_boxes, tx_outputs, 0, fee, change_address, min_change_value)
.set_data_inputs(data_inputs);
const tx_builder = TxBuilder.new(BoxSelector.SelectAll, unspent_boxes, tx_outputs, 0, fee, change_address, min_change_value);
tx_builder.set_data_inputs(data_inputs);
const tx = tx_builder.build();
assert(tx != null);
});


it('sign transaction', async () => {
const sk = SecretKey.random_dlog();
// simulate existing box guarded by the sk key
Expand Down
1 change: 1 addition & 0 deletions ergo-lib/src/chain/ergo_box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use super::{
token::{TokenAmount, TokenId},
transaction::TxId,
};

use crate::{
ergo_tree::ErgoTree,
serialization::{
Expand Down