Skip to content

Commit

Permalink
fix neo contract call param (#88)
Browse files Browse the repository at this point in the history
* publish v0.4 to crates.io

* hot fix vm value builder

* clean

* fix

* fmt

* fix import
  • Loading branch information
laizy authored Sep 7, 2020
1 parent 046028f commit d90e902
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 17 deletions.
10 changes: 8 additions & 2 deletions examples/call-neovm/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![feature(proc_macro_hygiene)]
#![no_std]
extern crate ontio_std as ostd;
use ostd::abi::{Sink, Source, VmValueParser};
use ostd::abi::{Sink, Source, VmValueBuilder, VmValueParser};
use ostd::contract::neo;
use ostd::prelude::*;
use ostd::runtime;
Expand Down Expand Up @@ -53,7 +53,13 @@ pub fn invoke() {
}
b"balanceOf" => {
let addr: Address = source.read().unwrap();
let res = neo::call_contract(&NEO_CONTRACT_ADDR, ("balanceOf", addr));
let mut builder = VmValueBuilder::new();
builder.string("balanceOf");
let mut nested = builder.list();
nested.address(&addr);
nested.finish();

let res = runtime::call_contract(&NEO_CONTRACT_ADDR, &builder.bytes());
let mut parser = VmValueParser::new(&res);
let r = parser.bytearray().unwrap_or(b"0");
sink.write(u128_from_neo_bytes(r));
Expand Down
2 changes: 1 addition & 1 deletion ontio-std/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ontio-std"
version = "0.3.0"
version = "0.4.0"
authors = ["laizy <[email protected]>"]
edition = "2018"
license = "Apache-2.0/MIT"
Expand Down
5 changes: 3 additions & 2 deletions ontio-std/src/abi/event_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,16 +118,17 @@ impl EventBuilder {
}
}

pub(crate) struct VmValueBuilderCommon {
pub struct VmValueBuilderCommon {
pub(crate) sink: Sink,
num_entry: u32,
pub(crate) num_entry: u32,
}

impl VmValueBuilderCommon {
pub(crate) fn new() -> Self {
let sink = Sink::new(12);
Self { sink, num_entry: 0u32 }
}

pub fn string(&mut self, method: &str) {
self.sink.write_byte(TYPE_STRING);
self.sink.write_u32(method.len() as u32);
Expand Down
92 changes: 80 additions & 12 deletions ontio-std/src/abi/vm_value_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use super::event_builder::{
use super::Error;
use super::Source;
use super::{VmValueBuilderCommon, VmValueDecoder, VmValueEncoder};
use crate::abi::event_builder::TYPE_LIST;
use crate::prelude::*;
use core::ops::{Deref, DerefMut};

pub struct VmValueBuilder {
pub(crate) common: VmValueBuilderCommon,
Expand All @@ -16,11 +18,40 @@ impl Default for VmValueBuilder {
}
}

pub struct NestedVmValueBuilder<'a> {
origin: &'a mut VmValueBuilder,
current: VmValueBuilderCommon,
}

impl<'a> NestedVmValueBuilder<'_> {
pub fn finish(self) {
let mut buf = self.current.sink.into();
buf[1..5].copy_from_slice(&self.current.num_entry.to_le_bytes());
self.origin.common.sink.write_bytes(&buf);
}
}

impl<'a> Deref for NestedVmValueBuilder<'a> {
type Target = VmValueBuilderCommon;

fn deref(&self) -> &Self::Target {
&self.current
}
}

impl<'a> DerefMut for NestedVmValueBuilder<'a> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.current
}
}

impl VmValueBuilder {
pub fn new() -> Self {
let common = VmValueBuilderCommon::new();
let mut builder = VmValueBuilder { common };
builder.common.sink.write_byte(0u8);
builder.common.sink.write_byte(0u8); // verison
builder.common.sink.write_byte(TYPE_LIST); // list type
builder.common.sink.write_u32(builder.common.num_entry); // occupy length
builder
}

Expand All @@ -44,6 +75,15 @@ impl VmValueBuilder {
self.common.number(amount);
}

pub fn list(&mut self) -> NestedVmValueBuilder {
let mut nested = VmValueBuilderCommon::new();
nested.sink.write_byte(TYPE_LIST); // list type
nested.sink.write_u32(0); // occupy length
self.common.num_entry += 1;

NestedVmValueBuilder { origin: self, current: nested }
}

pub fn bool(&mut self, b: bool) {
self.common.bool(b);
}
Expand All @@ -53,7 +93,10 @@ impl VmValueBuilder {
}

pub fn bytes(self) -> Vec<u8> {
self.common.sink.into()
let num_entry = self.common.num_entry;
let mut buf = self.common.sink.into();
buf[2..6].copy_from_slice(&num_entry.to_le_bytes());
buf
}
}

Expand Down Expand Up @@ -109,17 +152,11 @@ impl<'a> VmValueParser<'a> {

pub fn bool(&mut self) -> Result<bool, Error> {
let ty = self.source.read_byte()?;
if ty == TYPE_BOOL {
return self.source.read_bool();
} else if ty == TYPE_INT {
let res = self.source.read_u128()?;
if res != 0 {
return Ok(true);
} else {
return Ok(false);
}
match ty {
TYPE_BOOL => self.source.read_bool(),
TYPE_INT => Ok(self.source.read_u128()? != 0),
_ => Err(Error::TypeInconsistency),
}
Err(Error::TypeInconsistency)
}

pub fn h256(&mut self) -> Result<&'a H256, Error> {
Expand All @@ -130,3 +167,34 @@ impl<'a> VmValueParser<'a> {
self.source.read_h256()
}
}

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

#[test]
fn test_builder() {
let mut builder = VmValueBuilder::new();
let addr = Address::default();
builder.string("balanceOf");
let mut nested = builder.list();
nested.address(&addr);
nested.finish();

let mut sink = Sink::new(10);
sink.write_byte(0); //version
sink.write_byte(TYPE_LIST); // type
sink.write_u32(2); // two param
sink.write_byte(TYPE_STRING); // first param
let param = "balanceOf";
sink.write_u32(param.len() as u32);
sink.write_bytes(param.as_bytes());

sink.write_byte(TYPE_LIST); // second param
sink.write_u32(1);
sink.write_byte(TYPE_ADDRESS); // first param
sink.write(&addr);
assert_eq!(builder.bytes(), sink.into());
}
}

0 comments on commit d90e902

Please sign in to comment.