Skip to content

Commit

Permalink
Merge pull request #60 from bluele/release/v0.4.4
Browse files Browse the repository at this point in the history
Release v0.4.4
  • Loading branch information
bluele authored Sep 16, 2019
2 parents 01f847a + 1ede770 commit 9a4b02c
Show file tree
Hide file tree
Showing 22 changed files with 894 additions and 210 deletions.
5 changes: 2 additions & 3 deletions hmcdk/codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ pub fn contract(_attr: TokenStream, item: TokenStream) -> TokenStream {
}
},
Ok(None) => 0,
Err(e) => {
log(&format!("{:?}", e).as_str().as_bytes());
-1
Err(e) => match return_value(&format!("{:?}", e).as_str().as_bytes()) {
_ => -1,
}
}
}
Expand Down
30 changes: 21 additions & 9 deletions hmcdk/lib/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,23 +73,23 @@ extern "C" {
pub fn keccak256(msg: &[u8]) -> Result<[u8; 32], Error> {
let mut buf = [0u8; 32];
match unsafe { __keccak256(msg.as_ptr(), msg.len(), buf.as_mut_ptr(), buf.len()) } {
-1 => Err(from_str("failed to call keccak256")),
-1 => Err(from_str("__keccak256: failed to __keccak256")),
_ => Ok(buf),
}
}

pub fn sha256(msg: &[u8]) -> Result<[u8; 32], Error> {
let mut buf = [0u8; 32];
match unsafe { __sha256(msg.as_ptr(), msg.len(), buf.as_mut_ptr(), buf.len()) } {
-1 => Err(from_str("failed to call sha256")),
-1 => Err(from_str("__sha256: failed to __sha256")),
_ => Ok(buf),
}
}

pub fn emit_event<T: Into<String>>(name: T, value: &[u8]) -> Result<(), Error> {
let n = name.into();
match unsafe { __emit_event(n.as_ptr(), n.len(), value.as_ptr(), value.len()) } {
-1 => Err(from_str("failed to emit event")),
-1 => Err(from_str("__emit_event: failed to __emit_event")),
_ => Ok(()),
}
}
Expand Down Expand Up @@ -131,7 +131,9 @@ pub fn ecrecover(h: &[u8], v: &[u8], r: &[u8], s: &[u8]) -> Result<[u8; 65], Err
buf.len(),
)
} {
-1 => Err(from_str("failed to ecrecover")),
-1 => Err(from_str(
"__ecrecover_address: failed to __ecrecover_address",
)),
_ => Ok(buf),
}
}
Expand Down Expand Up @@ -173,7 +175,9 @@ pub fn ecrecover_address(h: &[u8], v: &[u8], r: &[u8], s: &[u8]) -> Result<Addre
buf.len(),
)
} {
-1 => Err(from_str("failed to ecrecover")),
-1 => Err(from_str(
"__ecrecover_address: failed to __ecrecover_address",
)),
_ => Ok(buf),
}
}
Expand All @@ -184,7 +188,7 @@ pub fn get_arg<T: FromBytes>(idx: usize) -> Result<T, Error> {
let mut val: Vec<u8> = Vec::new();
loop {
match unsafe { __get_arg(idx, offset, buf.as_mut_ptr(), buf.len()) } {
-1 => return Err(from_str("read_state: key not found")),
-1 => return Err(from_str(format!("__get_arg: index not found: {}", idx))),
0 => break,
n => {
val.extend_from_slice(&buf[0..n as usize]);
Expand All @@ -201,15 +205,17 @@ pub fn get_arg<T: FromBytes>(idx: usize) -> Result<T, Error> {
pub fn get_sender() -> Result<Address, Error> {
let mut buf: Address = Default::default();
match unsafe { __get_sender(buf.as_mut_ptr(), 20) } {
-1 => Err(from_str("sender not found")),
-1 => Err(from_str("__get_sender: failed to __get_sender")),
_ => Ok(buf),
}
}

pub fn get_contract_address() -> Result<Address, Error> {
let mut buf: Address = Default::default();
match unsafe { __get_contract_address(buf.as_mut_ptr(), 20) } {
-1 => Err(from_str("contract address not found")),
-1 => Err(from_str(
"__get_contract_address: failed to __get_contract_address",
)),
_ => Ok(buf),
}
}
Expand Down Expand Up @@ -283,7 +289,13 @@ pub fn read_state<T: FromBytes>(key: &[u8]) -> Result<T, Error> {
val_buf.len(),
)
} {
-1 => return Err(from_str("read_state: key not found")),
-1 => {
return Err(from_str(format!(
"__read_state: key not found {:?}({})",
key,
String::from_utf8(key.to_vec()).unwrap_or_else(|_| "INVALID UTF8".to_string())
)))
}
0 => break,
n => {
val.extend_from_slice(&val_buf[0..n as usize]);
Expand Down
4 changes: 2 additions & 2 deletions pkg/app/cmd/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ func vmCmd(ctx *app.Context) *cobra.Command {
return err
}
cms.Commit()
pretty.Println(res.RWSets)
fmt.Printf("RWSetsHash is '0x%x'\n", res.RWSets.Hash())
pretty.Println(res.State.RWSets())
fmt.Printf("RWSetsHash is '0x%x'\n", res.State.RWSets().Hash())
fmt.Println("response:", string(res.Response))
return nil
},
Expand Down
86 changes: 63 additions & 23 deletions pkg/client/cmd/contract/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ import (
"context"
"fmt"

"github.com/bluele/hypermint/pkg/abci/types"
"github.com/bluele/hypermint/pkg/client"
"github.com/bluele/hypermint/pkg/contract"
"github.com/bluele/hypermint/pkg/contract/event"
"github.com/bluele/hypermint/pkg/util"

ethcmn "github.com/ethereum/go-ethereum/common"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/tendermint/tendermint/libs/common"
"github.com/tendermint/tendermint/types"
tmtypes "github.com/tendermint/tendermint/types"
)

func init() {
Expand All @@ -26,7 +29,8 @@ func EventCMD() *cobra.Command {
// common
const (
flagContractAddress = "address"
flagEventName = "event"
flagEventName = "event.name"
flagEventValue = "event.value"
)

var subscribeCmd = &cobra.Command{
Expand Down Expand Up @@ -54,25 +58,13 @@ func EventCMD() *cobra.Command {
return err
}
for ev := range out {
etx := ev.Data.(types.EventDataTx)
etx := ev.Data.(tmtypes.EventDataTx)
fmt.Printf("TxID=0x%x\n", etx.Tx.Hash())
for _, ev := range etx.Result.Events {
if ev.Type != "contract" {
continue
}
for _, tag := range ev.Attributes {
if k := string(tag.GetKey()); k == "event.data" {
ev, err := contract.ParseEventData(tag.GetValue())
if err != nil {
return err
}
fmt.Println(ev.String())
} else if k == "event.name" || k == "address" {
// skip
} else {
fmt.Printf("unknown event: %v\n", tag)
}
}
printEvents([]types.Event{types.Event(ev)})
}
}
return nil
Expand Down Expand Up @@ -101,29 +93,77 @@ func EventCMD() *cobra.Command {
if err != nil {
return err
}
q := fmt.Sprintf("contract.address='%v' AND contract.event.name='%v'", viper.GetString(flagContractAddress), viper.GetString(flagEventName))
contractAddr := ethcmn.HexToAddress(viper.GetString(flagContractAddress))
q, err := event.MakeEventSearchQuery(
contractAddr,
viper.GetString(flagEventName),
viper.GetString(flagEventValue),
)
if err != nil {
return err
}
res, err := cl.TxSearch(q, true, 0, 0)
if err != nil {
return err
}

if viper.GetBool(flagCount) {
fmt.Print(len(res.Txs))
var count int
for _, tx := range res.Txs {
events, err := event.GetContractEventsFromResultTx(contractAddr, tx)
if err != nil {
return err
}
if len(events) == 0 {
continue
}
events, err = event.FilterContractEvents(
events,
viper.GetString(flagEventName),
viper.GetString(flagEventValue),
)
if err != nil {
return err
}
if len(events) == 0 {
continue
}
count++
}
fmt.Print(count)
return nil
} else {
for _, tx := range res.Txs {
fmt.Println(tx.TxResult.String())
fmt.Printf("Tx=0x%x\n", tx.Tx.Hash())
events, err := event.GetContractEventsFromResultTx(contractAddr, tx)
if err != nil {
return err
}
printEvents(events)
}
}
return nil
},
}

searchCmd.Flags().String(flagContractAddress, "", "contract address for subscription")
searchCmd.Flags().String(flagEventName, "", "event name for subscription")
searchCmd.Flags().Bool(flagCount, false, "if true, only print count of txs")
searchCmd.Flags().String(flagEventName, "", "event name")
searchCmd.Flags().String(flagEventValue, "", "event value as hex string")
searchCmd.Flags().Bool(flagCount, false, "if true, only print count of matched txs")
util.CheckRequiredFlag(searchCmd, flagContractAddress, flagEventName)
eventCmd.AddCommand(searchCmd)

return eventCmd
}

func printEvents(events []types.Event) {
for _, ev := range events {
fmt.Printf("event type=%v\n", ev.Type)
es, err := event.GetEntryFromEvent(ev)
if err != nil {
panic(err)
}
for _, entry := range es {
fmt.Printf("\tname=%v value=%v\n", string(entry.Name), string(entry.Value))
}
}
}
51 changes: 41 additions & 10 deletions pkg/contract/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package contract
import (
"fmt"

"github.com/bluele/hypermint/pkg/contract/event"
"github.com/bluele/hypermint/pkg/db"
"github.com/bluele/hypermint/pkg/logger"

Expand All @@ -22,9 +23,9 @@ type Env struct {
Contract *Contract
VMProvider VMProvider

DB *db.VersionedDB
state db.RWSets
events []*Event
DB *db.VersionedDB
entries []*event.Entry
state State
}

type Args struct {
Expand Down Expand Up @@ -62,6 +63,32 @@ func NewArgsFromStrings(ss []string) Args {
return Args{values: values}
}

type State struct {
rws db.RWSets
evs []*event.Event
}

func (s State) RWSets() db.RWSets {
return s.rws
}

func (s State) Events() []*event.Event {
return s.evs
}

func (s *State) Update(other State) {
s.AddRWSets(other.rws...)
s.AddEvents(other.evs...)
}

func (s *State) AddRWSets(ss ...*db.RWSet) {
s.rws.Add(ss...)
}

func (s *State) AddEvents(evs ...*event.Event) {
s.evs = append(s.evs, evs...)
}

type VMProvider func(*Env) (*VM, error)

func DefaultVMProvider(env *Env) (*VM, error) {
Expand All @@ -83,8 +110,7 @@ type VM struct {
type Result struct {
Code int32
Response []byte
RWSets db.RWSets
Events []*Event
State State
}

func (env *Env) Exec(ctx sdk.Context, entry string) (*Result, error) {
Expand All @@ -107,18 +133,23 @@ func (env *Env) Exec(ctx sdk.Context, entry string) (*Result, error) {
return nil, err
}
code := int32(ret)
res := env.GetReponse()
if code < 0 {
return &Result{Code: code}, fmt.Errorf("execute contract error(exit code: %v)", code)
// TODO add error msg from call stacks
return &Result{Code: code, Response: res}, fmt.Errorf("execute contract error exitcode=%v description=%v", code, string(res))
}
env.state.Add(&db.RWSet{

// Update state
env.state.AddRWSets(&db.RWSet{
Address: env.Contract.Address(),
Items: env.DB.RWSetItems(),
})
env.state.AddEvents(event.NewEvent(env.Contract.Address(), env.entries))

return &Result{
Code: code,
Response: env.GetReponse(),
RWSets: env.state,
Events: env.events,
Response: res,
State: env.state,
}, nil
}

Expand Down
Loading

0 comments on commit 9a4b02c

Please sign in to comment.