From 52fe710d466f678ccdb2ebbe4f07a4d141fc7149 Mon Sep 17 00:00:00 2001 From: Kiyoshi Ikehara Date: Wed, 9 Oct 2019 22:56:17 +0900 Subject: [PATCH 01/24] add abi package --- abi/abi.go | 74 ++++++++++++ abi/argument.go | 85 +++++++++++++ abi/bind/args.go | 27 +++++ abi/bind/auth.go | 46 ++++++++ abi/bind/backend.go | 41 +++++++ abi/bind/bind.go | 71 +++++++++++ abi/bind/bind_test.go | 34 ++++++ abi/bind/contract.go | 77 ++++++++++++ abi/bind/event.go | 69 +++++++++++ abi/bind/event_test.go | 55 +++++++++ abi/bind/primitives.go | 109 +++++++++++++++++ abi/bind/template.go | 256 ++++++++++++++++++++++++++++++++++++++++ abi/bind/transaction.go | 30 +++++ abi/bind/types.go | 15 +++ abi/event.go | 13 ++ abi/function.go | 44 +++++++ abi/struct.go | 13 ++ abi/type.go | 136 +++++++++++++++++++++ abi/types.go | 5 + 19 files changed, 1200 insertions(+) create mode 100644 abi/abi.go create mode 100644 abi/argument.go create mode 100644 abi/bind/args.go create mode 100644 abi/bind/auth.go create mode 100644 abi/bind/backend.go create mode 100644 abi/bind/bind.go create mode 100644 abi/bind/bind_test.go create mode 100644 abi/bind/contract.go create mode 100644 abi/bind/event.go create mode 100644 abi/bind/event_test.go create mode 100644 abi/bind/primitives.go create mode 100644 abi/bind/template.go create mode 100644 abi/bind/transaction.go create mode 100644 abi/bind/types.go create mode 100644 abi/event.go create mode 100644 abi/function.go create mode 100644 abi/struct.go create mode 100644 abi/type.go create mode 100644 abi/types.go diff --git a/abi/abi.go b/abi/abi.go new file mode 100644 index 0000000..a8a23ed --- /dev/null +++ b/abi/abi.go @@ -0,0 +1,74 @@ +package abi + +import ( + "encoding/json" + "fmt" + "github.com/iancoleman/strcase" + "io/ioutil" +) + +type ABI struct { + Functions []Function `json:"functions"` + Events []Event `json:"events"` + Structs []Struct `json:"structs"` +} + +func (e *ABI) UnmarshalJSON(data []byte) error { + var fields []struct { + Type string `json:"type"` + Name string `json:"name"` + Simulate bool `json:"simulate"` + Encoding string `json:"encoding"` + Inputs Arguments `json:"inputs"` + Outputs Arguments `json:"outputs"` + } + if err := json.Unmarshal(data, &fields); err != nil { + return err + } + for _, field := range fields { + switch field.Type { + case "function": + e.Functions = append(e.Functions, Function{ + Type: field.Type, + Name: strcase.ToCamel(field.Name), + RawName: field.Name, + Simulate: field.Simulate, + Inputs: field.Inputs, + Outputs: field.Outputs, + }) + case "event": + e.Events = append(e.Events, Event{ + Type: field.Type, + Name: strcase.ToCamel(field.Name), + RawName: field.Name, + Encoding: field.Encoding, + Inputs: field.Inputs, + }) + case "struct": + e.Structs = append(e.Structs, Struct{ + Type: field.Type, + Name: strcase.ToCamel(field.Name), + RawName: field.Name, + Encoding: field.Encoding, + Inputs: field.Inputs, + }) + default: + return fmt.Errorf("unknown type: %v", field.Type) + } + } + return nil +} + +func Unmarshal(data []byte) (*ABI, error) { + var abi ABI + err := json.Unmarshal(data, &abi) + return &abi, err +} + +func ReadJsonFile(filename string) (*ABI, error) { + if bytes, err := ioutil.ReadFile(filename); err != nil { + return nil, err + } else { + return Unmarshal(bytes) + } +} diff --git a/abi/argument.go b/abi/argument.go new file mode 100644 index 0000000..fae4260 --- /dev/null +++ b/abi/argument.go @@ -0,0 +1,85 @@ +package abi + +import ( + "encoding/json" + "fmt" + "github.com/iancoleman/strcase" +) + +type Argument struct { + Type Type + Name string + PubName string +} + +type Arguments []Argument + +func typeFromName(typeName string) (*Type, error) { + var t byte + switch typeName { + case "i8": + t = I8Ty + case "i16": + t = I16Ty + case "i32": + t = I32Ty + case "i64": + t = I64Ty + case "u8": + t = U8Ty + case "u16": + t = U16Ty + case "u32": + t = U32Ty + case "u64": + t = U64Ty + case "bool": + t = BoolTy + case "bytes": + t = BytesTy + case "str": + t = StringTy + case "address": + t = AddressTy + case "hash": + t = HashTy + default: + return nil, fmt.Errorf("unknown type: %v", typeName) + } + return &Type{ + Name: typeName, + T: t, + }, nil +} + +func (a *Argument) UnmarshalJSON(data []byte) error { + var fields struct { + Type string `json:"type"` + Name string `json:"name"` + } + err := json.Unmarshal(data, &fields) + if err != nil { + return err + } + if ty, err := typeFromName(fields.Type); err != nil { + return err + } else { + a.Type = *ty + } + a.Name = fields.Name + if a.Name == "" { + a.Name = "_" + } + a.PubName = strcase.ToCamel(fields.Name) + return nil +} + +func (a *Argument) MarshalJSON() ([]byte, error) { + var fields struct { + Type string `json:"type"` + Name string `json:"name"` + } + fields.Type = a.Type.Name + fields.Name = a.Name + return json.Marshal(fields) +} diff --git a/abi/bind/args.go b/abi/bind/args.go new file mode 100644 index 0000000..e32611b --- /dev/null +++ b/abi/bind/args.go @@ -0,0 +1,27 @@ +package bind + +import ( + "bytes" + "encoding/gob" +) + +type Arg interface { + Bytes() []byte +} + +func Args(args ...Arg) [][]byte { + var bss [][]byte + for _, arg := range args { + bss = append(bss, arg.Bytes()) + } + return bss +} + +func DeepCopy(dst, src interface{}) error { + var buf bytes.Buffer + if err := gob.NewEncoder(&buf).Encode(src); err != nil { + return err + } + return gob.NewDecoder(bytes.NewBuffer(buf.Bytes())).Decode(dst) +} + diff --git a/abi/bind/auth.go b/abi/bind/auth.go new file mode 100644 index 0000000..22593e1 --- /dev/null +++ b/abi/bind/auth.go @@ -0,0 +1,46 @@ +package bind + +import ( + "crypto/ecdsa" + "errors" + "github.com/bluele/hypermint/pkg/transaction" + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" +) + +func NewKeyedTransactor(key *ecdsa.PrivateKey) *TransactOpts { + keyAddr := crypto.PubkeyToAddress(key.PublicKey) + return &TransactOpts{ + From: keyAddr, + Signer: func(tx transaction.Transaction, address common.Address) (transaction.Transaction, error) { + if address != keyAddr { + return nil, errors.New("not authorized to sign this account") + } + signature, err := crypto.Sign(tx.GetSignBytes(), key) + if err != nil { + return nil, err + } + tx.SetSignature(signature) + return tx, nil + }, + } +} + +func NewKeyStoreTransactor(keystore *keystore.KeyStore, account accounts.Account) (*TransactOpts, error) { + return &TransactOpts{ + From: account.Address, + Signer: func(tx transaction.Transaction, address common.Address) (transaction.Transaction, error) { + if address != account.Address { + return nil, errors.New("not authorized to sign this account") + } + signature, err := keystore.SignHash(account, tx.GetSignBytes()) + if err != nil { + return nil, err + } + tx.SetSignature(signature) + return tx, nil + }, + }, nil +} diff --git a/abi/bind/backend.go b/abi/bind/backend.go new file mode 100644 index 0000000..fa0532b --- /dev/null +++ b/abi/bind/backend.go @@ -0,0 +1,41 @@ +package bind + +import ( + "context" + "github.com/bluele/hypermint/pkg/contract/event" + "github.com/bluele/hypermint/pkg/transaction" + "github.com/ethereum/go-ethereum/common" +) + +type AsyncResult struct { + TxHash common.Hash +} + +type SyncResult struct { + TxHash common.Hash +} + +type CommitResult struct { + TxHash common.Hash + Height int64 + Entries []*event.Entry +} + +type ContractTransactor interface { + BroadcastTxAsync(ctx context.Context, tx transaction.Transaction) (*AsyncResult, error) + BroadcastTxSync(ctx context.Context, tx transaction.Transaction) (*SyncResult, error) + BroadcastTxCommit(ctx context.Context, tx transaction.Transaction) (*CommitResult, error) +} + +type SimulateResult struct { + Data []byte +} + +type ContractSimulator interface { + SimulateTx(ctx context.Context, tx transaction.Transaction) (*SimulateResult, error) +} + +type ContractBackend interface { + ContractSimulator + ContractTransactor +} diff --git a/abi/bind/bind.go b/abi/bind/bind.go new file mode 100644 index 0000000..22141ff --- /dev/null +++ b/abi/bind/bind.go @@ -0,0 +1,71 @@ +package bind + +import ( + "bytes" + "encoding/json" + "fmt" + "github.com/bluele/hypermint/abi" + "github.com/iancoleman/strcase" + "go/format" + "strings" + "text/template" +) + +type tmplContract struct { + Type string + Transacts []abi.Function + Events []abi.Event + Structs []abi.Struct + InputABI string +} + +type tmplData struct { + Package string + Contracts map[string]tmplContract + Mock bool +} + +func Bind(packageName string, name, jsonABI string, mock bool) (string, error) { + buffer := new(bytes.Buffer) + + abi, err := abi.Unmarshal([]byte(jsonABI)) + if err != nil { + return "", err + } + + var packBuf bytes.Buffer + packEnc := json.NewEncoder(&packBuf) + err = packEnc.Encode(abi) + if err != nil { + return "", err + } + inputABI := strings.TrimRight(packBuf.String(), "\n") + + contracts := make(map[string]tmplContract) + c := tmplContract{ + Type: strcase.ToCamel(name), + Transacts: abi.Functions, + Events: abi.Events, + Structs: abi.Structs, + InputABI: strings.Replace(inputABI, "\"", "\\\"", -1), + } + + contracts[name] = c + + data := &tmplData{ + Package: packageName, + Contracts: contracts, + Mock: mock, + } + + tmpl := template.Must(template.New("").Parse(tmplGoSource)) + if err := tmpl.Execute(buffer, data); err != nil { + return "", err + } + + code, err := format.Source(buffer.Bytes()) + if err != nil { + return "", fmt.Errorf("%v\n%s", err, buffer) + } + return string(code), nil +} diff --git a/abi/bind/bind_test.go b/abi/bind/bind_test.go new file mode 100644 index 0000000..e52a6d4 --- /dev/null +++ b/abi/bind/bind_test.go @@ -0,0 +1,34 @@ +package bind + +import "testing" + +func TestBind(t *testing.T) { + src, err := Bind("main", "test", ` +[ + { + "type": "function", + "name": "hoge", + "inputs": [ + { + "name": "piyo", + "type": "address" + }, + { + "name": "unko", + "type": "u64" + } + ], + "outputs": [ + { + "name": "", + "type": "u64" + } + ] + } +] +`, true) + if err != nil { + t.Error(err) + } + t.Log(src) +} diff --git a/abi/bind/contract.go b/abi/bind/contract.go new file mode 100644 index 0000000..ad5afbe --- /dev/null +++ b/abi/bind/contract.go @@ -0,0 +1,77 @@ +package bind + +import ( + "errors" + "github.com/ethereum/go-ethereum/common" +) + +type BoundContract struct { + address common.Address + transactor ContractTransactor + simulator ContractSimulator +} + +func NewBoundContract(address common.Address, simulator ContractSimulator, transactor ContractTransactor) *BoundContract { + return &BoundContract{ + address: address, + transactor: transactor, + simulator: simulator, + } +} + +func (b *BoundContract) Transact(opt *TransactOpts, fn string, args... []byte) (*SyncResult, error) { + return b.TransactWithRWH(opt, fn, nil, args...) +} + +func (b *BoundContract) TransactWithRWH(opt *TransactOpts, fn string, rwh []byte, args... []byte) (*SyncResult, error) { + tx, err := MakeContractCallTx(opt.From, b.address, fn, args, rwh) + if err != nil { + return nil, err + } + if opt.Signer == nil { + return nil, errors.New("no signer") + } + signedTx, err := opt.Signer(tx, opt.From) + if err != nil { + return nil, err + } + return b.transactor.BroadcastTxSync(opt.Context, signedTx) +} + +func (b *BoundContract) TransactCommit(opt *TransactOpts, fn string, args... []byte) (*CommitResult, error) { + return b.TransactCommitWithRWH(opt, fn, nil, args...) +} + +func (b *BoundContract) TransactCommitWithRWH(opt *TransactOpts, fn string, rwh []byte, args... []byte) (*CommitResult, error) { + tx, err := MakeContractCallTx(opt.From, b.address, fn, args, rwh) + if err != nil { + return nil, err + } + if opt.Signer == nil { + return nil, errors.New("no signer") + } + signedTx, err := opt.Signer(tx, opt.From) + if err != nil { + return nil, err + } + return b.transactor.BroadcastTxCommit(opt.Context, signedTx) +} + +func (b *BoundContract) Simulate(opt *TransactOpts, fn string, args ...[]byte) (*SimulateResult, error) { + return b.SimulateTxWithRWH(opt, fn, nil, args...) +} + +func (b *BoundContract) SimulateTxWithRWH(opt *TransactOpts, fn string, rwh []byte, args ...[]byte) (*SimulateResult, error) { + tx, err := MakeContractCallTx(opt.From, b.address, fn, args, rwh) + if err != nil { + return nil, err + } + if opt.Signer == nil { + return nil, errors.New("no signer") + } + signedTx, err := opt.Signer(tx, opt.From) + if err != nil { + return nil, err + } + return b.simulator.SimulateTx(opt.Context, signedTx) +} diff --git a/abi/bind/event.go b/abi/bind/event.go new file mode 100644 index 0000000..7bd9c0c --- /dev/null +++ b/abi/bind/event.go @@ -0,0 +1,69 @@ +package bind + +import ( + "errors" + "fmt" + "github.com/bluele/hypermint/pkg/contract/event" + "reflect" +) + +var ErrTypeMismatch = errors.New("type mismatch") +var ErrUnknownType = errors.New("unknown type") +var ErrNotFound = errors.New("event not found") + +type Event interface { + Decode(bs []byte) error +} + +type EventInfo struct { + ID string + EventCreator func() Event +} + +type EventDecoder struct { + events map[string]EventInfo +} + +func NewEventDecoder() *EventDecoder { + return &EventDecoder{ + events: make(map[string]EventInfo), + } +} + +func (d *EventDecoder) Register(event EventInfo) { + d.events[event.ID] = event +} + +func (d *EventDecoder) Decode(v interface{}, entry *event.Entry) error { + if reflect.Ptr != reflect.ValueOf(v).Kind() { + return fmt.Errorf("abi: Decode(non-pointer %T)", v) + } + ei, ok := d.events[string(entry.Name)] + if !ok { + return ErrUnknownType + } + e := ei.EventCreator() + if reflect.Ptr != reflect.ValueOf(e).Kind() { + return fmt.Errorf("abi: Decode(non-pointer %T)", e) + } + if reflect.TypeOf(v) != reflect.TypeOf(e) { + return ErrTypeMismatch + } + err := e.Decode(entry.Value) + if err != nil { + return err + } + reflect.ValueOf(v).Elem().Set(reflect.ValueOf(e).Elem()) + return nil +} + +func (d *EventDecoder) FindFirst(v interface{}, entries []*event.Entry) error { + for _, e := range entries { + if err := d.Decode(v, e); err != nil && err != ErrTypeMismatch { + return err + } else if err == nil { + return nil + } + } + return ErrNotFound +} diff --git a/abi/bind/event_test.go b/abi/bind/event_test.go new file mode 100644 index 0000000..9822017 --- /dev/null +++ b/abi/bind/event_test.go @@ -0,0 +1,55 @@ +package bind + +import ( + "encoding/json" + "github.com/bluele/hypermint/pkg/contract/event" + "github.com/ethereum/go-ethereum/common" + "testing" +) + +type TransferRaw struct { + From Address `json:"from"` + To Address `json:"to"` + TokenID U64 `json:"tokenID"` +} + +type Transfer struct { + From common.Address + To common.Address + TokenID uint64 +} + +func (_Transfer *Transfer) Decode(bs []byte) error { + var raw TransferRaw + if err := json.Unmarshal(bs, &raw); err != nil { + return err + } + if err := DeepCopy(_Transfer, &raw); err != nil { + return err + } + return nil +} + +var TransferInfo = EventInfo { + ID: "Transfer", + EventCreator: func() Event { + return &Transfer{} + }, +} + +func TestEventDecoder_Decode(t *testing.T) { + d := NewEventDecoder() + d.Register(TransferInfo) + + var transfer Transfer + e := event.Entry { + Name: []byte("Transfer"), + Value: []byte(`{"from":[147,48,98,172,145,177,43,39,168,143,13,143,0,190,158,208,81,63,13,20],"to":[184,50,15,186,149,14,223,23,8,253,230,160,55,12,232,148,209,89,99,57],"tokenID":18}`), + } + if err := d.Decode(&transfer, &e); err != nil { + t.Error(err) + } + if transfer.TokenID != 18 { + t.Fail() + } +} diff --git a/abi/bind/primitives.go b/abi/bind/primitives.go new file mode 100644 index 0000000..e23c521 --- /dev/null +++ b/abi/bind/primitives.go @@ -0,0 +1,109 @@ +package bind + +import ( + "encoding/binary" + "encoding/json" + "github.com/ethereum/go-ethereum/common" +) + +type Bool bool + +func (b Bool) Bytes() []byte { + if b { + return []byte{1} + } else { + return []byte{0} + } +} + +type I8 int8 + +func (i I8) Bytes() []byte { + return []byte{byte(i)} +} + +type I16 int16 + +func (i I16) Bytes() []byte { + v := make([]byte, 2) + binary.BigEndian.PutUint16(v, uint16(i)) + return v +} + +type I32 int32 + +func (i I32) Bytes() []byte { + v := make([]byte, 4) + binary.BigEndian.PutUint32(v, uint32(i)) + return v +} + +type I64 int64 + +func (i I64) Bytes() []byte { + v := make([]byte, 8) + binary.BigEndian.PutUint64(v, uint64(i)) + return v +} + +type U8 uint8 + +func (u U8) Bytes() []byte { + return []byte{byte(u)} +} + +type U16 uint16 + +func (u U16) Bytes() []byte { + v := make([]byte, 2) + binary.BigEndian.PutUint16(v, uint16(u)) + return v +} + +type U32 uint32 + +func (u U32) Bytes() []byte { + v := make([]byte, 4) + binary.BigEndian.PutUint32(v, uint32(u)) + return v +} + +type U64 uint64 + +func (u U64) Bytes() []byte { + v := make([]byte, 8) + binary.BigEndian.PutUint64(v, uint64(u)) + return v +} + +type String string + +func (s String) Bytes() []byte { + return []byte(s) +} + +type Address common.Address + +func (a Address) Bytes() []byte { + return common.Address(a).Bytes() +} + +func (a *Address) MarshalJSON() ([]byte, error) { + ua := []uint8(a.Bytes()) + return json.Marshal(ua) +} + +func (a *Address) UnmarshalJSON(bs []byte) error { + var ua [20]uint8 + if err := json.Unmarshal(bs, &ua); err != nil { + return err + } + *a = Address(common.Address(ua)) + return nil +} + +type Hash common.Hash + +func (a Hash) Bytes() []byte { + return common.Hash(a).Bytes() +} diff --git a/abi/bind/template.go b/abi/bind/template.go new file mode 100644 index 0000000..7e5961f --- /dev/null +++ b/abi/bind/template.go @@ -0,0 +1,256 @@ +package bind + +const tmplGoSource = ` +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package {{.Package}} + +import ( + "encoding/binary" + "bytes" + "encoding/json" + + "github.com/bluele/hypermint/abi/bind" + "github.com/bluele/hypermint/pkg/transaction" + "github.com/ethereum/go-ethereum/common" +{{if .Mock}} + "github.com/stretchr/testify/mock" +{{end}} +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = bind.Bind + _ = common.Big1 + _ = transaction.ContractInitFunc + _ = bytes.NewBuffer + _ = binary.Read + _ = json.NewEncoder +) + +{{range $contract := .Contracts}} + var {{.Type}}ABI string = "{{ .InputABI }}" + + {{range .Structs}} + {{if eq .Encoding "json"}} + type {{$contract.Type}}{{.Name}}Raw struct { + {{range .Inputs -}} + {{.PubName}} {{.Type.BoundType}} `+"`"+`json:"{{.Name}}"`+"`"+` + {{end}} + } + {{else}} + type {{$contract.Type}}{{.Name}}Raw struct { + {{range .Inputs -}} + {{.PubName}} {{.Type.TypeName}} + {{end}} + } + {{end}} + + type {{$contract.Type}}{{.Name}} struct { + {{range .Inputs -}} + {{.PubName}} {{.Type.TypeName}} `+"`"+`json:"{{.Name}}"`+"`"+` + {{end}} + } + + {{if eq .Encoding "json"}} + func (_{{.Name}} *{{$contract.Type}}{{.Name}}) Decode(bs []byte) error { + var raw {{$contract.Type}}{{.Name}}Raw + if err := json.Unmarshal(bs, &raw); err != nil { + return err + } + if err := bind.DeepCopy(_{{.Name}}, &raw); err != nil { + return err + } + return nil + } + {{end}} + {{end}} + + {{range .Events}} + {{if eq .Encoding "json"}} + type {{$contract.Type}}{{.Name}}Raw struct { + {{range .Inputs -}} + {{.PubName}} {{.Type.BoundType}} `+"`"+`json:"{{.Name}}"`+"`"+` + {{end}} + } + {{else}} + type {{$contract.Type}}{{.Name}}Raw struct { + {{range .Inputs -}} + {{.PubName}} {{.Type.TypeName}} + {{end}} + } + {{end}} + + type {{$contract.Type}}{{.Name}} struct { + {{range .Inputs -}} + {{.PubName}} {{.Type.TypeName}} `+"`"+`json:"{{.Name}}"`+"`"+` + {{end}} + } + + {{if eq .Encoding "json"}} + func (_{{.Name}} *{{$contract.Type}}{{.Name}}) Decode(bs []byte) error { + var raw {{$contract.Type}}{{.Name}}Raw + if err := json.Unmarshal(bs, &raw); err != nil { + return err + } + if err := bind.DeepCopy(_{{.Name}}, &raw); err != nil { + return err + } + return nil + } + {{end}} + {{end}} + + var {{.Type}}EventDecoder = bind.NewEventDecoder() + + {{range .Events}} + var {{$contract.Type}}{{.Name}}Info = bind.EventInfo { + ID: "{{.Name}}", + EventCreator: func() bind.Event { + return &{{$contract.Type}}{{.Name}}{} + }, + } + {{end}} + + func init() { + {{range .Events -}} + {{$contract.Type}}EventDecoder.Register({{$contract.Type}}{{.Name}}Info) + {{end -}} + } + + type {{.Type}}Contract interface { + {{range .Transacts}} + {{if .Simulate}} + {{.Name}}(opts *bind.TransactOpts {{range .Inputs}}, {{.Name}} {{.Type.TypeName}}{{end}}) ({{range .Outputs}}{{.Type.TypeName}}, {{end}}error) + {{else}} + {{.Name}}(opts *bind.TransactOpts {{range .Inputs}}, {{.Name}} {{.Type.TypeName}}{{end}}) (*bind.SyncResult, error) + {{.Name}}Commit(opts *bind.TransactOpts {{range .Inputs}}, {{.Name}} {{.Type.TypeName}}{{end}}) (*bind.CommitResult, error) + {{end}} + {{end}} + } + + type {{.Type}} struct { + {{.Type}}Simulator // Read-only binding to the contract + {{.Type}}Transactor // Write-only binding to the contract + } + + type {{.Type}}Simulator struct { + contract *bind.BoundContract + } + + type {{.Type}}Transactor struct { + contract *bind.BoundContract + } + + type {{.Type}}Raw struct { + Contract *{{.Type}} + } + + type {{.Type}}SimulatorRaw struct { + Contract *{{.Type}}Simulator + } + + type {{.Type}}TransactorRaw struct { + Contract *{{.Type}}Transactor + } + + func New{{.Type}}(address common.Address, backend bind.ContractBackend) (*{{.Type}}, error) { + contract, err := bind{{.Type}}(address, backend, backend) + if err != nil { + return nil, err + } + return &{{.Type}}{ {{.Type}}Simulator: {{.Type}}Simulator{contract: contract}, {{.Type}}Transactor: {{.Type}}Transactor{contract: contract} }, nil + } + + func New{{.Type}}Simulator(address common.Address, simulator bind.ContractSimulator) (*{{.Type}}Simulator, error) { + contract, err := bind{{.Type}}(address, simulator, nil) + if err != nil { + return nil, err + } + return &{{.Type}}Simulator{contract: contract}, nil + } + + func New{{.Type}}Transactor(address common.Address, transactor bind.ContractTransactor) (*{{.Type}}Transactor, error) { + contract, err := bind{{.Type}}(address, nil, transactor) + if err != nil { + return nil, err + } + return &{{.Type}}Transactor{contract: contract}, nil + } + + func bind{{.Type}}(address common.Address, simulator bind.ContractSimulator, transactor bind.ContractTransactor) (*bind.BoundContract, error) { + return bind.NewBoundContract(address, simulator, transactor), nil + } + + func (_{{$contract.Type}} *{{$contract.Type}}Raw) Transact(opts *bind.TransactOpts, fn string, params ...[]byte) (*bind.SyncResult, error) { + return _{{$contract.Type}}.Contract.{{$contract.Type}}Transactor.contract.Transact(opts, fn, params...) + } + + func (_{{$contract.Type}} *{{$contract.Type}}SimulatorRaw) Simulate(opts *bind.TransactOpts, fn string, params ...[]byte) (*bind.SimulateResult, error) { + return _{{$contract.Type}}.Contract.contract.Simulate(opts, fn, params...) + } + + {{range .Transacts}} + {{if .Simulate}} + func (_{{$contract.Type}} *{{$contract.Type}}Simulator) {{.Name}}(opts *bind.TransactOpts {{range .Inputs}}, {{.Name}} {{.Type.TypeName}}{{end}}) ({{range .Outputs}}{{.Type.TypeName}}, {{end}}error) { + {{if .Outputs}}result{{else}}_{{end}}, err := _{{$contract.Type}}.contract.Simulate(opts, "{{.RawName}}", bind.Args({{range .Inputs}} + {{.Type.ToBoundType .Name}},{{end}})...) + if err != nil { + return {{range .Outputs}}{{.Type.Nil}}, {{end}}err + } + {{if .Outputs}} + buf := bytes.NewBuffer(result.Data) + {{end}} + {{range $i, $v := .Outputs -}} + {{if eq .Type.TypeName "string"}} + var v{{ $i }} {{.Type.TypeName}} + v{{ $i }} = buf.String() + {{else}} + var v{{ $i }} {{.Type.TypeName}} + binary.Read(buf, binary.BigEndian, &v{{ $i }}) + {{end}} + {{end -}} + return {{range $i, $v := .Outputs}}v{{ $i }}, {{end}}nil + } + {{else}} + func (_{{$contract.Type}} *{{$contract.Type}}Transactor) {{.Name}}(opts *bind.TransactOpts {{range .Inputs}}, {{.Name}} {{.Type.TypeName}}{{end}}) (*bind.SyncResult, error) { + return _{{$contract.Type}}.contract.Transact(opts, "{{.RawName}}", bind.Args({{range .Inputs}} + {{.Type.ToBoundType .Name}},{{end}})...) + } + + func (_{{$contract.Type}} *{{$contract.Type}}Transactor) {{.Name}}Commit(opts *bind.TransactOpts {{range .Inputs}}, {{.Name}} {{.Type.TypeName}}{{end}}) (*bind.CommitResult, error) { + return _{{$contract.Type}}.contract.TransactCommit(opts, "{{.RawName}}", bind.Args({{range .Inputs}} + {{.Type.ToBoundType .Name}},{{end}})...) + } + {{end}} + {{end}} +{{end}} + +{{if .Mock}} + {{range $contract := .Contracts}} + type Mock{{.Type}} struct { + mock.Mock + } + + {{range .Transacts}} + {{if .Simulate}} + func (_{{$contract.Type}} *Mock{{$contract.Type}}) {{.Name}}(opts *bind.TransactOpts {{range .Inputs}}, {{.Name}} {{.Type.TypeName}}{{end}}) ({{range .Outputs}}{{.Type.TypeName}}, {{end}}error) { + ret := _{{$contract.Type}}.Called({{range .Inputs}}{{.Name}}, {{end}}) + return {{range $i, $v := .Outputs}}ret.Get({{$i}}).({{.Type.TypeName}}), {{end}}ret.Error({{len .Outputs}}) + } + {{else}} + func (_{{$contract.Type}} *Mock{{$contract.Type}}) {{.Name}}(opts *bind.TransactOpts {{range .Inputs}}, {{.Name}} {{.Type.TypeName}}{{end}}) (*bind.SyncResult, error) { + ret := _{{$contract.Type}}.Called({{range .Inputs}}{{.Name}}, {{end}}) + return ret.Get(0).(*bind.SyncResult), ret.Error(1) + } + + func (_{{$contract.Type}} *Mock{{$contract.Type}}) {{.Name}}Commit(opts *bind.TransactOpts {{range .Inputs}}, {{.Name}} {{.Type.TypeName}}{{end}}) (*bind.CommitResult, error) { + ret := _{{$contract.Type}}.Called({{range .Inputs}}{{.Name}}, {{end}}) + return ret.Get(0).(*bind.CommitResult), ret.Error(1) + } + {{end}} + {{end}} + {{end}} +{{end}} +` diff --git a/abi/bind/transaction.go b/abi/bind/transaction.go new file mode 100644 index 0000000..a707571 --- /dev/null +++ b/abi/bind/transaction.go @@ -0,0 +1,30 @@ +package bind + +import ( + "github.com/bluele/hypermint/pkg/transaction" + "github.com/ethereum/go-ethereum/common" +) + +func MakeContractCallTx(callerAddress, contractAddress common.Address, fn string, args [][]byte, rwh []byte) (transaction.Transaction, error) { + nonce, err := transaction.GetNonceByAddress(callerAddress) + if err != nil { + return nil, err + } + var byteArgs [][]byte + for _, arg := range args { + byteArgs = append(byteArgs, arg) + } + return &transaction.ContractCallTx{ + Common: transaction.CommonTx{ + Code: transaction.CONTRACT_CALL, + From: callerAddress, + Nonce: nonce, + Gas: 1, + Signature: nil, + }, + Address: contractAddress, + Func: fn, + Args: byteArgs, + RWSetsHash: rwh, + }, nil +} diff --git a/abi/bind/types.go b/abi/bind/types.go new file mode 100644 index 0000000..ba8ef8f --- /dev/null +++ b/abi/bind/types.go @@ -0,0 +1,15 @@ +package bind + +import ( + "context" + "github.com/bluele/hypermint/pkg/transaction" + "github.com/ethereum/go-ethereum/common" +) + +type SignerFn func(tx transaction.Transaction, addr common.Address) (transaction.Transaction, error) + +type TransactOpts struct { + From common.Address + Signer SignerFn + Context context.Context +} diff --git a/abi/event.go b/abi/event.go new file mode 100644 index 0000000..c071a84 --- /dev/null +++ b/abi/event.go @@ -0,0 +1,13 @@ +package abi + +type Event struct { + RawName string `json:"name"` + Name string `json:"-"` + Type string `json:"type"` + Encoding string `json:"encoding"` + Inputs Arguments `json:"inputs"` +} + +func (e Event) GetName() string { + return e.Name +} diff --git a/abi/function.go b/abi/function.go new file mode 100644 index 0000000..978acea --- /dev/null +++ b/abi/function.go @@ -0,0 +1,44 @@ +package abi + +import ( + "fmt" + "strings" +) + +type Function struct { + RawName string `json:"name"` + Name string `json:"-"` + Type string `json:"type"` + Simulate bool `json:"simulate"` + Inputs Arguments `json:"inputs"` + Outputs Arguments `json:"outputs"` +} + +func (f Function) GetName() string { + return f.Name +} + +// TODO +func (f Function) Sig() string { + types := make([]string, len(f.Inputs)) + for i, input := range f.Inputs { + types[i] = input.Type.String() + } + return fmt.Sprintf("%v(%v)", f.RawName, strings.Join(types, ",")) +} + +// TODO +func (f Function) String() string { + inputs := make([]string, len(f.Inputs)) + for i, input := range f.Inputs { + inputs[i] = fmt.Sprintf("%v %v", input.Type, input.Name) + } + outputs := make([]string, len(f.Outputs)) + for i, output := range f.Outputs { + outputs[i] = output.Type.String() + if len(output.Name) > 0 { + outputs[i] += fmt.Sprintf(" %v", output.Name) + } + } + return fmt.Sprintf("function %v(%v) returns(%v)", f.RawName, strings.Join(inputs, ", "), strings.Join(outputs, ", ")) +} diff --git a/abi/struct.go b/abi/struct.go new file mode 100644 index 0000000..d4e3479 --- /dev/null +++ b/abi/struct.go @@ -0,0 +1,13 @@ +package abi + +type Struct struct { + RawName string `json:"name"` + Name string `json:"-"` + Type string `json:"type"` + Encoding string `json:"encoding"` + Inputs Arguments `json:"inputs"` +} + +func (s Struct) GetName() string { + return s.Name +} diff --git a/abi/type.go b/abi/type.go new file mode 100644 index 0000000..73975c4 --- /dev/null +++ b/abi/type.go @@ -0,0 +1,136 @@ +package abi + +import "fmt" + +const ( + I8Ty byte = iota + I16Ty + I32Ty + I64Ty + U8Ty + U16Ty + U32Ty + U64Ty + BoolTy + BytesTy + StringTy + AddressTy + HashTy +) + +type Type struct { + Name string // ABI type name + T byte // type code +} + +// as string +func (t Type) String() string { + return t.Name +} + +func (t Type) TypeName() string { + switch t.T { + case I8Ty: + return "int8" + case I16Ty: + return "int16" + case I32Ty: + return "int32" + case I64Ty: + return "int64" + case U8Ty: + return "uint8" + case U16Ty: + return "uint16" + case U32Ty: + return "uint32" + case U64Ty: + return "uint64" + case BoolTy: + return "bool" + case BytesTy: + return "[]byte" + case StringTy: + return "string" + case AddressTy: + return "common.Address" + case HashTy: + return "common.Hash" + default: + panic(fmt.Errorf("unknown type: %v", t.T)) + } +} + +func (t Type) Nil() string { + switch t.T { + case I8Ty: + return "int8(0)" + case I16Ty: + return "int16(0)" + case I32Ty: + return "int32(0)" + case I64Ty: + return "int64(0)" + case U8Ty: + return "uint8(0)" + case U16Ty: + return "uint16(0)" + case U32Ty: + return "uint32(0)" + case U64Ty: + return "uint64(0)" + case StringTy: + return "\"\"" + case BytesTy: + return "nil" + case BoolTy: + return "false" + case AddressTy: + return "common.Address{}" + case HashTy: + return "common.Hash{}" + default: + panic(fmt.Errorf("unknown type: %v", t.T)) + } +} + +func (t Type) ToBoundType(s string) string { + return t.BoundType() + "(" + s + ")" +} + +func (t Type) FromBoundType(s string) string { + return t.TypeName() + "(" + s + ")" +} + +func (t Type) BoundType() string { + var op string + switch t.T { + case I8Ty: + op = "bind.I8" + case I16Ty: + op = "bind.I16" + case I32Ty: + op = "bind.I32" + case I64Ty: + op = "bind.I64" + case U8Ty: + op = "bind.U8" + case U16Ty: + op = "bind.U16" + case U32Ty: + op = "bind.U32" + case U64Ty: + op = "bind.U64" + case BoolTy: + op = "bind.Bool" + case StringTy: + op = "bind.String" + case AddressTy: + op = "bind.Address" + case HashTy: + op = "bind.Hash" + default: + panic(fmt.Errorf("unknown type: %v", t.T)) + } + return op +} diff --git a/abi/types.go b/abi/types.go new file mode 100644 index 0000000..cc650cc --- /dev/null +++ b/abi/types.go @@ -0,0 +1,5 @@ +package abi + +type Element interface { + GetName() string +} From f5ea79c341a159ff4980c70aecff907660262628 Mon Sep 17 00:00:00 2001 From: Kiyoshi Ikehara Date: Wed, 9 Oct 2019 22:56:44 +0900 Subject: [PATCH 02/24] add client package --- client/client.go | 151 +++++++++++++++++++++++++++++++++++++++++++++++ client/error.go | 5 ++ 2 files changed, 156 insertions(+) create mode 100644 client/client.go create mode 100644 client/error.go diff --git a/client/client.go b/client/client.go new file mode 100644 index 0000000..c0c2c87 --- /dev/null +++ b/client/client.go @@ -0,0 +1,151 @@ +package client + +import ( + "context" + "github.com/bluele/hypermint/pkg/abci/codec" + hmabcitypes "github.com/bluele/hypermint/pkg/abci/types" + "github.com/bluele/hypermint/abi/bind" + "github.com/bluele/hypermint/pkg/contract/event" + "github.com/bluele/hypermint/pkg/handler" + "github.com/bluele/hypermint/pkg/transaction" + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + "github.com/tendermint/go-amino" + tmabcitypes "github.com/tendermint/tendermint/abci/types" + rpcClient "github.com/tendermint/tendermint/rpc/client" + rpcTypes "github.com/tendermint/tendermint/rpc/core/types" + "strings" +) + +type Signer func(msg []byte, addr []byte) ([]byte, error) + +type Client struct { + Client rpcClient.Client +} + +func NewClient(conn string) *Client { + c := rpcClient.NewHTTP(conn, "/websocket") + return &Client{ + Client: c, + } +} + +func (c Client) SimulateTx(ctx context.Context, tx transaction.Transaction) (*bind.SimulateResult, error) { + if data, err := c.simulateTx(tx); err != nil { + return nil, err + } else { + res := new(handler.ContractCallTxResponse) + if err := amino.UnmarshalBinaryBare(data, res); err != nil { + return nil, err + } + return &bind.SimulateResult{ + Data: res.Returned, + }, err + } +} + +func (c *Client) simulateTx(tx transaction.Transaction) ([]byte, error) { + res, err := c.Client.ABCIQuery("/app/simulate", tx.Bytes()) + if err != nil { + return nil, err + } + var result hmabcitypes.Result + codec.Cdc.MustUnmarshalBinaryLengthPrefixed(res.Response.Value, &result) + + if result.Code != 0 { + return result.Data, errors.Errorf("Simulate failed: (%d) %s", + result.Code, result.Log) + } + + return result.Data, nil +} + +func (c *Client) BroadcastTxAsync(ctx context.Context, tx transaction.Transaction) (*bind.AsyncResult, error) { + res, err := c.Client.BroadcastTxAsync(tx.Bytes()) + if err != nil { + return nil, err + } + return &bind.AsyncResult{ + TxHash: common.BytesToHash(res.Hash.Bytes()), + }, nil +} + +func (c *Client) BroadcastTxSync(ctx context.Context, tx transaction.Transaction) (*bind.SyncResult, error) { + res, err := c.Client.BroadcastTxSync(tx.Bytes()) + if err != nil { + return nil, err + } + return &bind.SyncResult{ + TxHash: common.BytesToHash(res.Hash.Bytes()), + }, nil +} + +func (c *Client) BroadcastTxCommit(ctx context.Context, tx transaction.Transaction) (*bind.CommitResult, error) { + res, err := c.Client.BroadcastTxCommit(tx.Bytes()) + if err != nil && res != nil { + if res.CheckTx.GetCode() == 104 && strings.Contains(err.Error(), "already exists:") { + return nil, ErrAlreadyExists + } + } + if err != nil { + return nil, err + } + + var events []tmabcitypes.Event + events = res.DeliverTx.Events + var entries []*event.Entry + for _, tme := range events { + es, err := event.GetEntryFromEvent(hmabcitypes.Event(tme)) + if err != nil { + return nil, err + } + entries = append(entries, es...) + } + + return &bind.CommitResult{ + TxHash: common.BytesToHash(res.Hash.Bytes()), + Height: res.Height, + Entries: entries, + }, nil +} + +func (c *Client) TransactionEventEntries(ctx context.Context, txHash common.Hash) ([]*event.Entry, error) { + resultTx, err := c.transactionByHash(txHash.Bytes()) + if err != nil { + return nil, err + } + tx, error := transaction.DecodeTx(resultTx.Tx) + if error != nil { + return nil, errors.New(error.Error()) + } + switch tx := tx.(type) { + case *transaction.ContractCallTx: + events, err := event.GetContractEventsFromResultTx(tx.Address, resultTx) + if err != nil { + return nil, err + } + var entries []*event.Entry + for _, tme := range events { + es, err := event.GetEntryFromEvent(tme) + if err != nil { + return nil, err + } + entries = append(entries, es...) + } + return entries, nil + default: + return nil, errors.New("invalid transaction type") + } +} + +func (c *Client) transactionByHash(txHash []byte) (*rpcTypes.ResultTx, error) { + resultTx, err := c.Client.Tx(txHash, false) + if err != nil { + return nil, err + } + result := resultTx.TxResult + if result.Code != 0 { + return resultTx, errors.Errorf("Tx failed: (%d) %s", result.Code, result.Log) + } + return resultTx, nil +} diff --git a/client/error.go b/client/error.go new file mode 100644 index 0000000..ac115eb --- /dev/null +++ b/client/error.go @@ -0,0 +1,5 @@ +package client + +import "errors" + +var ErrAlreadyExists = errors.New("contract already exists") From 1a236c60bb65a342fa1e61a3afa44cece90cbb12 Mon Sep 17 00:00:00 2001 From: Kiyoshi Ikehara Date: Wed, 9 Oct 2019 22:57:14 +0900 Subject: [PATCH 03/24] add abigen command --- cmd/abigen/.gitignore | 1 + cmd/abigen/Makefile | 11 +++ cmd/abigen/README.md | 9 ++ cmd/abigen/cmd.go | 68 ++++++++++++++ cmd/abigen/cmd_test.go | 10 ++ cmd/abigen/example/token.go | 167 ++++++++++++++++++++++++++++++++++ cmd/abigen/example/token.json | 1 + cmd/abigen/main.go | 5 + 8 files changed, 272 insertions(+) create mode 100644 cmd/abigen/.gitignore create mode 100644 cmd/abigen/Makefile create mode 100644 cmd/abigen/README.md create mode 100644 cmd/abigen/cmd.go create mode 100644 cmd/abigen/cmd_test.go create mode 100755 cmd/abigen/example/token.go create mode 100644 cmd/abigen/example/token.json create mode 100644 cmd/abigen/main.go diff --git a/cmd/abigen/.gitignore b/cmd/abigen/.gitignore new file mode 100644 index 0000000..7f0286d --- /dev/null +++ b/cmd/abigen/.gitignore @@ -0,0 +1 @@ +/abigen diff --git a/cmd/abigen/Makefile b/cmd/abigen/Makefile new file mode 100644 index 0000000..f231bd4 --- /dev/null +++ b/cmd/abigen/Makefile @@ -0,0 +1,11 @@ + +.PHONY: test +test: + go build + ./abigen --outdir example --name token --package main --abi example/token.json --mock + (cd example && go test) + +.PHONY: gen-example +gen-example: + mkdir -p example + (cd ../../hmcdk/genabi && cargo run ../../example/token/src/lib.rs) > example/token.json diff --git a/cmd/abigen/README.md b/cmd/abigen/README.md new file mode 100644 index 0000000..6ff3443 --- /dev/null +++ b/cmd/abigen/README.md @@ -0,0 +1,9 @@ +# abigen + +A go-ethereum like contract call code generator from ABI json + +## Test + +``` +$ make example +``` diff --git a/cmd/abigen/cmd.go b/cmd/abigen/cmd.go new file mode 100644 index 0000000..44f7499 --- /dev/null +++ b/cmd/abigen/cmd.go @@ -0,0 +1,68 @@ +package main + +import ( + "errors" + "fmt" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "io/ioutil" + "os" + "path" + "strings" + "github.com/bluele/hypermint/abi/bind" +) + +var rootCmd = &cobra.Command{ + Use: "abigen", + Short: "Code generation from ABI", + RunE: func(cmd *cobra.Command, args []string) error { + if err := viper.BindPFlags(cmd.Flags()); err != nil { + return err + } + pkg := viper.GetString("package") + outdir := viper.GetString("outdir") + if len(outdir) == 0 { + outdir = pkg + } + name := viper.GetString("name") + if len(name) == 0 { + return errors.New("name not specified") + } + abi := viper.GetString("abi") + mock := viper.GetBool("mock") + return Generate(outdir, pkg, name, abi, mock) + }, +} + +func Generate(outdir, pkg, name, abiJsonFilename string, mock bool) error { + if abiJson, err := ioutil.ReadFile(abiJsonFilename); err != nil { + return err + } else if src, err := bind.Bind(pkg, name, string(abiJson), mock); err != nil { + return err + } else { + if err := os.MkdirAll(pkg, 0700); err != nil { + return err + } + if err := ioutil.WriteFile(path.Join(outdir, name+".go"), []byte(src), 0700); err != nil { + return err + } + return nil + } +} + +func init() { + rootCmd.Flags().String("package", "contract", "package name") + rootCmd.Flags().String("name", "", "contract name") + rootCmd.Flags().String("abi", "example.json", "abi json") + rootCmd.Flags().String("outdir", "", "output dir") + rootCmd.Flags().Bool("mock", false, "generate mock") + viper.AutomaticEnv() + viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) +} + +func Execute() { + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} diff --git a/cmd/abigen/cmd_test.go b/cmd/abigen/cmd_test.go new file mode 100644 index 0000000..6d8eb66 --- /dev/null +++ b/cmd/abigen/cmd_test.go @@ -0,0 +1,10 @@ +package main + +import "testing" + +func TestGenerate(t *testing.T) { + err := Generate("example", "main", "token", "example/token.json", true) + if err != nil { + t.Error(err) + } +} diff --git a/cmd/abigen/example/token.go b/cmd/abigen/example/token.go new file mode 100755 index 0000000..4466073 --- /dev/null +++ b/cmd/abigen/example/token.go @@ -0,0 +1,167 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package main + +import ( + "bytes" + "encoding/binary" + "encoding/json" + + "github.com/bluele/hypermint/abi/bind" + "github.com/bluele/hypermint/pkg/transaction" + "github.com/ethereum/go-ethereum/common" + + "github.com/stretchr/testify/mock" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = bind.Bind + _ = common.Big1 + _ = transaction.ContractInitFunc + _ = bytes.NewBuffer + _ = binary.Read + _ = json.NewEncoder +) + +var TokenABI string = "{\"functions\":[{\"name\":\"get_balance\",\"type\":\"function\",\"simulate\":true,\"inputs\":[],\"outputs\":[{\"type\":\"i64\",\"name\":\"_\"}]},{\"name\":\"transfer\",\"type\":\"function\",\"simulate\":false,\"inputs\":[{\"type\":\"address\",\"name\":\"to\"},{\"type\":\"i64\",\"name\":\"amount\"}],\"outputs\":[{\"type\":\"i64\",\"name\":\"_\"}]},{\"name\":\"init\",\"type\":\"function\",\"simulate\":false,\"inputs\":[],\"outputs\":[{\"type\":\"bytes\",\"name\":\"_\"}]}],\"events\":null,\"structs\":null}" + +var TokenEventDecoder = bind.NewEventDecoder() + +func init() { +} + +type TokenContract interface { + GetBalance(opts *bind.TransactOpts) (int64, error) + + Transfer(opts *bind.TransactOpts, to common.Address, amount int64) (*bind.SyncResult, error) + TransferCommit(opts *bind.TransactOpts, to common.Address, amount int64) (*bind.CommitResult, error) + + Init(opts *bind.TransactOpts) (*bind.SyncResult, error) + InitCommit(opts *bind.TransactOpts) (*bind.CommitResult, error) +} + +type Token struct { + TokenSimulator // Read-only binding to the contract + TokenTransactor // Write-only binding to the contract +} + +type TokenSimulator struct { + contract *bind.BoundContract +} + +type TokenTransactor struct { + contract *bind.BoundContract +} + +type TokenRaw struct { + Contract *Token +} + +type TokenSimulatorRaw struct { + Contract *TokenSimulator +} + +type TokenTransactorRaw struct { + Contract *TokenTransactor +} + +func NewToken(address common.Address, backend bind.ContractBackend) (*Token, error) { + contract, err := bindToken(address, backend, backend) + if err != nil { + return nil, err + } + return &Token{TokenSimulator: TokenSimulator{contract: contract}, TokenTransactor: TokenTransactor{contract: contract}}, nil +} + +func NewTokenSimulator(address common.Address, simulator bind.ContractSimulator) (*TokenSimulator, error) { + contract, err := bindToken(address, simulator, nil) + if err != nil { + return nil, err + } + return &TokenSimulator{contract: contract}, nil +} + +func NewTokenTransactor(address common.Address, transactor bind.ContractTransactor) (*TokenTransactor, error) { + contract, err := bindToken(address, nil, transactor) + if err != nil { + return nil, err + } + return &TokenTransactor{contract: contract}, nil +} + +func bindToken(address common.Address, simulator bind.ContractSimulator, transactor bind.ContractTransactor) (*bind.BoundContract, error) { + return bind.NewBoundContract(address, simulator, transactor), nil +} + +func (_Token *TokenRaw) Transact(opts *bind.TransactOpts, fn string, params ...[]byte) (*bind.SyncResult, error) { + return _Token.Contract.TokenTransactor.contract.Transact(opts, fn, params...) +} + +func (_Token *TokenSimulatorRaw) Simulate(opts *bind.TransactOpts, fn string, params ...[]byte) (*bind.SimulateResult, error) { + return _Token.Contract.contract.Simulate(opts, fn, params...) +} + +func (_Token *TokenSimulator) GetBalance(opts *bind.TransactOpts) (int64, error) { + result, err := _Token.contract.Simulate(opts, "get_balance", bind.Args()...) + if err != nil { + return int64(0), err + } + + buf := bytes.NewBuffer(result.Data) + + var v0 int64 + binary.Read(buf, binary.BigEndian, &v0) + + return v0, nil +} + +func (_Token *TokenTransactor) Transfer(opts *bind.TransactOpts, to common.Address, amount int64) (*bind.SyncResult, error) { + return _Token.contract.Transact(opts, "transfer", bind.Args( + bind.Address(to), + bind.I64(amount))...) +} + +func (_Token *TokenTransactor) TransferCommit(opts *bind.TransactOpts, to common.Address, amount int64) (*bind.CommitResult, error) { + return _Token.contract.TransactCommit(opts, "transfer", bind.Args( + bind.Address(to), + bind.I64(amount))...) +} + +func (_Token *TokenTransactor) Init(opts *bind.TransactOpts) (*bind.SyncResult, error) { + return _Token.contract.Transact(opts, "init", bind.Args()...) +} + +func (_Token *TokenTransactor) InitCommit(opts *bind.TransactOpts) (*bind.CommitResult, error) { + return _Token.contract.TransactCommit(opts, "init", bind.Args()...) +} + +type MockToken struct { + mock.Mock +} + +func (_Token *MockToken) GetBalance(opts *bind.TransactOpts) (int64, error) { + ret := _Token.Called() + return ret.Get(0).(int64), ret.Error(1) +} + +func (_Token *MockToken) Transfer(opts *bind.TransactOpts, to common.Address, amount int64) (*bind.SyncResult, error) { + ret := _Token.Called(to, amount) + return ret.Get(0).(*bind.SyncResult), ret.Error(1) +} + +func (_Token *MockToken) TransferCommit(opts *bind.TransactOpts, to common.Address, amount int64) (*bind.CommitResult, error) { + ret := _Token.Called(to, amount) + return ret.Get(0).(*bind.CommitResult), ret.Error(1) +} + +func (_Token *MockToken) Init(opts *bind.TransactOpts) (*bind.SyncResult, error) { + ret := _Token.Called() + return ret.Get(0).(*bind.SyncResult), ret.Error(1) +} + +func (_Token *MockToken) InitCommit(opts *bind.TransactOpts) (*bind.CommitResult, error) { + ret := _Token.Called() + return ret.Get(0).(*bind.CommitResult), ret.Error(1) +} diff --git a/cmd/abigen/example/token.json b/cmd/abigen/example/token.json new file mode 100644 index 0000000..6bee1c0 --- /dev/null +++ b/cmd/abigen/example/token.json @@ -0,0 +1 @@ +[{"type":"function","name":"get_balance","simulate":true,"inputs":[],"outputs":[{"type":"i64","name":""}]},{"type":"function","name":"transfer","simulate":false,"inputs":[{"type":"address","name":"to"},{"type":"i64","name":"amount"}],"outputs":[{"type":"i64","name":""}]},{"type":"function","name":"init","simulate":false,"inputs":[],"outputs":[{"type":"bytes","name":""}]}] diff --git a/cmd/abigen/main.go b/cmd/abigen/main.go new file mode 100644 index 0000000..736ef31 --- /dev/null +++ b/cmd/abigen/main.go @@ -0,0 +1,5 @@ +package main + +func main() { + Execute() +} From 735d2e9f89c5407cf751670599f1ed06664c2fef Mon Sep 17 00:00:00 2001 From: Kiyoshi Ikehara Date: Wed, 9 Oct 2019 22:57:55 +0900 Subject: [PATCH 04/24] add cligen command --- cli/bind/auth.go | 7 + cli/bind/bind.go | 92 ++++++++++++ cli/bind/flags.go | 41 ++++++ cli/bind/template.go | 224 +++++++++++++++++++++++++++++ cli/bind/unlock.go | 15 ++ cli/passphrase.go | 19 +++ cmd/cligen/.gitignore | 1 + cmd/cligen/Makefile | 11 ++ cmd/cligen/cmd.go | 73 ++++++++++ cmd/cligen/example/main.go | 32 +++++ cmd/cligen/example/token.go | 136 ++++++++++++++++++ cmd/cligen/example/token.json | 1 + cmd/cligen/example/tokencmd.go | 250 +++++++++++++++++++++++++++++++++ cmd/cligen/main.go | 5 + 14 files changed, 907 insertions(+) create mode 100644 cli/bind/auth.go create mode 100644 cli/bind/bind.go create mode 100644 cli/bind/flags.go create mode 100644 cli/bind/template.go create mode 100644 cli/bind/unlock.go create mode 100644 cli/passphrase.go create mode 100644 cmd/cligen/.gitignore create mode 100644 cmd/cligen/Makefile create mode 100644 cmd/cligen/cmd.go create mode 100644 cmd/cligen/example/main.go create mode 100755 cmd/cligen/example/token.go create mode 100644 cmd/cligen/example/token.json create mode 100755 cmd/cligen/example/tokencmd.go create mode 100644 cmd/cligen/main.go diff --git a/cli/bind/auth.go b/cli/bind/auth.go new file mode 100644 index 0000000..db089aa --- /dev/null +++ b/cli/bind/auth.go @@ -0,0 +1,7 @@ +package bind + +import "github.com/ethereum/go-ethereum/accounts/keystore" + +func NewKeyStore(keydir string) *keystore.KeyStore { + return keystore.NewKeyStore(keydir, keystore.StandardScryptN, keystore.StandardScryptP) +} diff --git a/cli/bind/bind.go b/cli/bind/bind.go new file mode 100644 index 0000000..a68b7ba --- /dev/null +++ b/cli/bind/bind.go @@ -0,0 +1,92 @@ +package bind + +import ( + "bytes" + "encoding/json" + "fmt" + "github.com/bluele/hypermint/abi" + "github.com/iancoleman/strcase" + "go/format" + "strings" + "text/template" +) + +type tmplFunction struct { + abi.Function + Use string + Short string +} + +type tmplContract struct { + Type string + Name string + Use string + Short string + Functions []tmplFunction + Events []abi.Event + Structs []abi.Struct + InputABI string +} + +type tmplData struct { + Package string + Contracts map[string]tmplContract + Endpoint string +} + +func Bind(packageName string, name, jsonABI string) (string, error) { + buffer := new(bytes.Buffer) + + abi, err := abi.Unmarshal([]byte(jsonABI)) + if err != nil { + return "", err + } + + var packBuf bytes.Buffer + packEnc := json.NewEncoder(&packBuf) + err = packEnc.Encode(abi) + if err != nil { + return "", err + } + inputABI := strings.TrimRight(packBuf.String(), "\n") + + var functions []tmplFunction + for _, f := range abi.Functions { + functions = append(functions, tmplFunction{ + Function: f, + Use: strcase.ToDelimited(f.Name, '-'), + Short: strcase.ToDelimited(f.Name, ' '), + }) + } + + contracts := make(map[string]tmplContract) + c := tmplContract{ + Type: strcase.ToCamel(name), + Name: name, + Use: name, + Short: name, + Functions: functions, + Events: abi.Events, + Structs: abi.Structs, + InputABI: strings.Replace(inputABI, "\"", "\\\"", -1), + } + + contracts[name] = c + + data := &tmplData{ + Package: packageName, + Contracts: contracts, + Endpoint: "tcp://localhost:26657", + } + + tmpl := template.Must(template.New("").Parse(tmplGoSource)) + if err := tmpl.Execute(buffer, data); err != nil { + return "", err + } + + code, err := format.Source(buffer.Bytes()) + if err != nil { + return "", fmt.Errorf("%v\n%s", err, buffer) + } + return string(code), nil +} diff --git a/cli/bind/flags.go b/cli/bind/flags.go new file mode 100644 index 0000000..77e5269 --- /dev/null +++ b/cli/bind/flags.go @@ -0,0 +1,41 @@ +package bind + +import ( + "fmt" + "github.com/bluele/hypermint/cli" + "github.com/ethereum/go-ethereum/common" + ) + +func GetFlagPassphrase(getPassphrase func() (string, error)) func() (string, error) { + return func() (string, error) { + passphrase, err := getPassphrase() + if err != nil { + if pp, err := cli.ReadPassphrase(); err != nil { + return "", err + } else { + return pp, nil + } + } else { + return passphrase, nil + } + } +} + +func GetFlagAddress(getAddress func() (string, error), alias map[string]common.Address) func() (common.Address, error) { + return func () (common.Address, error) { + var address common.Address + a, err := getAddress() + if err != nil { + return common.Address{}, err + } + if addr, ok := alias[a]; ok { + return addr, nil + } else { + if !common.IsHexAddress(a) { + return common.Address{}, fmt.Errorf("invalid address: %v", a) + } + address = common.HexToAddress(a) + } + return address, nil + } +} diff --git a/cli/bind/template.go b/cli/bind/template.go new file mode 100644 index 0000000..1160f44 --- /dev/null +++ b/cli/bind/template.go @@ -0,0 +1,224 @@ +package bind + +var tmplGoSource = ` +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package {{.Package}} + +import ( + "errors" + "os" + "fmt" + "math/big" + "strings" + "encoding/binary" + "bytes" + "encoding/json" + "github.com/spf13/cobra" + "github.com/spf13/viper" + + "github.com/bluele/hypermint/abi/bind" + clibind "github.com/bluele/hypermint/cli/bind" + "github.com/bluele/hypermint/client" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/accounts" + "github.com/bluele/hypermint/pkg/transaction" + "github.com/ethereum/go-ethereum/accounts/keystore" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = big.NewInt + _ = strings.NewReader + _ = bind.Bind + _ = clibind.Bind + _ = common.Big1 + _ = transaction.ContractInitFunc + _ = bytes.NewBuffer + _ = binary.Read + _ = json.NewEncoder +) + +{{$endpoint := .Endpoint}} +{{range $contract := .Contracts -}} + func {{.Type}}Cmd(contractAddress, callerAddress string) *cobra.Command { + var cmd = &cobra.Command{ + Use: "{{.Use}}", + Short: "{{.Short}}", + } + cmd.PersistentFlags().Bool("verbose", false, "verbose") + cmd.PersistentFlags().String("passphrase", "xxx", "passphrase") + cmd.PersistentFlags().String("caller", callerAddress, "caller") + cmd.PersistentFlags().String("contract", contractAddress, "contract") + cmd.PersistentFlags().String("endpoint", "{{$endpoint}}", "endpoint") + {{range .Functions -}} + cmd.AddCommand({{$contract.Name}}{{.Name}}Cmd) + {{end}} + return cmd + } + + {{$events := .Events}} + {{range .Functions}} + func init() { + {{if .Inputs}} + cmd := {{$contract.Name}}{{.Name}}Cmd + {{range .Inputs -}} + {{if eq .Type.Name "bool"}} + cmd.Flags().Bool("{{.Name}}", false, "{{.Name}}") + {{else}} + cmd.Flags().String("{{.Name}}", "", "{{.Name}}") + {{end}} + {{end -}} + {{end -}} + } + + var {{$contract.Name}}{{.Name}}Cmd = &cobra.Command{ + Use: "{{.Use}}", + Short: "{{.Short}}", + RunE: func(cmd *cobra.Command, args []string) error { + if err := viper.BindPFlags(cmd.Flags()); err != nil { + return err + } + verbose := viper.GetBool("verbose") + + {{range .Inputs}} + {{if eq .Type.Name "address"}} + if len(viper.GetString("{{.Name}}")) == 0 { + return errors.New("invalid address") + } + arg{{.Name}} := common.HexToAddress(viper.GetString("{{.Name}}")) + {{else if eq .Type.Name "hash"}} + if len(viper.GetString("{{.Name}}")) == 0 { + return errors.New("invalid hash") + } + arg{{.Name}} := common.HexToHash(viper.GetString("{{.Name}}")) + {{else if eq .Type.Name "bool"}} + arg{{.Name}} := viper.GetBool("{{.Name}}") + {{else}} + arg{{.Name}} := {{.Type.TypeName}}(viper.GetInt64("{{.Name}}")) + {{end}} + if verbose { + fmt.Fprintf(os.Stderr, "{{.Name}}=%v\n", arg{{.Name}}) + } + {{end}} + if verbose { + fmt.Fprintf(os.Stderr, "passphrase=%v\n", viper.GetString("passphrase")) + } + + ks := clibind.NewKeyStore("keystore") + opts, c, err := {{$contract.Name}}ContractFromFlags(ks) + if err != nil { + return err + } + {{if .Simulate}} + if verbose { + fmt.Fprintf(os.Stderr, "simulating {{.Name}}...") + } + {{range $i, $o := .Outputs}}v{{$i}}{{end}}, err := c.{{.Name}}( + opts, + {{range .Inputs -}} + arg{{.Name}}, + {{end}} + ) + if err != nil { + return err + } + if verbose { + fmt.Fprintf(os.Stderr, "done\n") + } + {{range $i, $o := .Outputs}} + {{if eq .Type.Name "address"}} + if _, err := fmt.Fprintln(os.Stdout, v{{$i}}.Hex()); err != nil { + return err + } + {{else}} + if _, err := fmt.Fprintln(os.Stdout, v{{$i}}); err != nil { + return err + } + {{end}} + {{end}} + return nil + {{else}} + if verbose { + fmt.Fprintf(os.Stderr, "committing {{.Name}}...") + } + r, err := c.{{.Name}}Commit( + opts, + {{range .Inputs -}} + arg{{.Name}}, + {{end}} + ) + if err != nil { + return err + } + if verbose { + fmt.Fprintf(os.Stderr, "%v\n", r.TxHash.Hex()) + } + ed := {{$contract.Type}}EventDecoder + if ed == nil { + return errors.New("{{$contract.Type}}EventDecoder is nil") + } + {{range $events}} + if verbose { + fmt.Fprintf(os.Stderr, "looking up {{$contract.Type}}{{.Name}}...") + } + var _{{.Name}} {{$contract.Type}}{{.Name}} + if err := ed.FindFirst(&_{{.Name}}, r.Entries); err != nil { + if verbose { + fmt.Fprintf(os.Stderr, "%v\n", err.Error()) + } + } else { + if verbose { + fmt.Fprintf(os.Stderr, "found\n") + } + json.NewEncoder(os.Stdout).Encode(&_{{.Name}}) + } + {{end}} + return nil + {{end}} + }, + } + {{end}} + + func {{.Name}}ContractFromFlags(ks *keystore.KeyStore) (*bind.TransactOpts, {{.Type}}Contract, error) { + pp, err := clibind.GetFlagPassphrase(func() (string, error) { + pp := viper.GetString("passphrase") + if pp == "xxx" { + return "", errors.New("passphrase required") + } + return pp, nil + })() + if err != nil { + return nil, nil, err + } + + caller := common.HexToAddress(viper.GetString("caller")) + if err := clibind.Unlock(ks, caller, pp); err != nil { + return nil, nil, err + } + + contractAddress, err := clibind.GetFlagAddress(func() (string, error) { + return viper.GetString("contract"), nil + }, nil)() + if err != nil { + return nil, nil, err + } + + opts, err := bind.NewKeyStoreTransactor(ks, accounts.Account{Address:caller}) + if err != nil { + return nil, nil, err + } + + endpoint := viper.GetString("endpoint") + cl := client.NewClient(endpoint) + c{{.Type}}, err := New{{.Type}}(contractAddress, cl) + if err != nil { + return nil, nil, err + } + + return opts, c{{.Type}}, nil + } + +{{end}} +` diff --git a/cli/bind/unlock.go b/cli/bind/unlock.go new file mode 100644 index 0000000..af8a53c --- /dev/null +++ b/cli/bind/unlock.go @@ -0,0 +1,15 @@ +package bind + +import ( + "fmt" + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/common" +) + +func Unlock(ks *keystore.KeyStore, address common.Address, passphrase string) error { + if !ks.HasAddress(address) { + return fmt.Errorf("account not found: %v", address.Hex()) + } + return ks.Unlock(accounts.Account{Address: address}, passphrase) +} diff --git a/cli/passphrase.go b/cli/passphrase.go new file mode 100644 index 0000000..cdd41e6 --- /dev/null +++ b/cli/passphrase.go @@ -0,0 +1,19 @@ +package cli + +import ( + "fmt" + "golang.org/x/crypto/ssh/terminal" + "os" + "syscall" +) + +func ReadPassphrase() (string, error) { + _, _ = fmt.Fprint(os.Stderr, "Passphrase: ") + password, err := terminal.ReadPassword(int(syscall.Stdin)) + _, _ = fmt.Fprintf(os.Stderr, "\n") + if err != nil { + return "", err + } else { + return string(password), nil + } +} diff --git a/cmd/cligen/.gitignore b/cmd/cligen/.gitignore new file mode 100644 index 0000000..0e28463 --- /dev/null +++ b/cmd/cligen/.gitignore @@ -0,0 +1 @@ +cligen diff --git a/cmd/cligen/Makefile b/cmd/cligen/Makefile new file mode 100644 index 0000000..e564ac5 --- /dev/null +++ b/cmd/cligen/Makefile @@ -0,0 +1,11 @@ + +.PHONY: test +test: + go build + ./cligen --outdir example --name token --package main --abi example/token.json + (cd example && go build) + +.PHONY: gen-example +gen-example: + mkdir -p example + (cd ../../hmcdk/genabi && cargo run ../../example/token/src/lib.rs) > example/token.json diff --git a/cmd/cligen/cmd.go b/cmd/cligen/cmd.go new file mode 100644 index 0000000..a78ecbb --- /dev/null +++ b/cmd/cligen/cmd.go @@ -0,0 +1,73 @@ +package main + +import ( + "errors" + "fmt" + "github.com/bluele/hypermint/abi/bind" + clibind "github.com/bluele/hypermint/cli/bind" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "io/ioutil" + "os" + "path" + "strings" +) + +var rootCmd = &cobra.Command{ + Use: "cligen", + Short: "Code generation from ABI", + RunE: func(cmd *cobra.Command, args []string) error { + if err := viper.BindPFlags(cmd.Flags()); err != nil { + return err + } + pkg := viper.GetString("package") + outdir := viper.GetString("outdir") + if len(outdir) == 0 { + outdir = pkg + } + name := viper.GetString("name") + if len(name) == 0 { + return errors.New("name not specified") + } + abi := viper.GetString("abi") + return Generate(outdir, pkg, name, abi) + }, +} + +func Generate(outdir, pkg, name, abiJsonFilename string) error { + if abiJson, err := ioutil.ReadFile(abiJsonFilename); err != nil { + return err + } else if boundSrc, err := bind.Bind(pkg, name, string(abiJson), false); err != nil { + return err + } else if src, err := clibind.Bind(pkg, name, string(abiJson)); err != nil { + return err + } else { + if err := os.MkdirAll(outdir, 0700); err != nil { + return err + } + if err := ioutil.WriteFile(path.Join(outdir, name+".go"), []byte(boundSrc), 0700); err != nil { + return err + } + if err := ioutil.WriteFile(path.Join(outdir, name+"cmd.go"), []byte(src), 0700); err != nil { + return err + } + return nil + } +} + + +func init() { + rootCmd.Flags().String("package", "contract", "package name") + rootCmd.Flags().String("name", "", "contract name") + rootCmd.Flags().String("abi", "example.json", "abi json") + rootCmd.Flags().String("outdir", "", "output dir") + viper.AutomaticEnv() + viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) +} + +func Execute() { + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} diff --git a/cmd/cligen/example/main.go b/cmd/cligen/example/main.go new file mode 100644 index 0000000..7db7776 --- /dev/null +++ b/cmd/cligen/example/main.go @@ -0,0 +1,32 @@ +package main + +import ( + "fmt" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "os" + "strings" +) + +var rootCmd = &cobra.Command{ + Use: "example", + Short: "Example CLI", +} + +const ( + TokenContractAddress = "0x3b74892E655c9E2e47f3442Ef64dA6766fd2a62c" + TokenCallerAddress = "0x933062aC91b12b27A88F0d8F00BE9eD0513f0D14" +) + +func init() { + rootCmd.AddCommand(TokenCmd(TokenContractAddress, TokenCallerAddress)) + viper.AutomaticEnv() + viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) +} + +func main() { + if err := rootCmd.Execute(); err != nil { + _, _ = fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} diff --git a/cmd/cligen/example/token.go b/cmd/cligen/example/token.go new file mode 100755 index 0000000..e430e53 --- /dev/null +++ b/cmd/cligen/example/token.go @@ -0,0 +1,136 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package main + +import ( + "bytes" + "encoding/binary" + "encoding/json" + + "github.com/bluele/hypermint/abi/bind" + "github.com/bluele/hypermint/pkg/transaction" + "github.com/ethereum/go-ethereum/common" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = bind.Bind + _ = common.Big1 + _ = transaction.ContractInitFunc + _ = bytes.NewBuffer + _ = binary.Read + _ = json.NewEncoder +) + +var TokenABI string = "{\"functions\":[{\"name\":\"get_balance\",\"type\":\"function\",\"simulate\":true,\"inputs\":[],\"outputs\":[{\"type\":\"i64\",\"name\":\"_\"}]},{\"name\":\"transfer\",\"type\":\"function\",\"simulate\":false,\"inputs\":[{\"type\":\"address\",\"name\":\"to\"},{\"type\":\"i64\",\"name\":\"amount\"}],\"outputs\":[{\"type\":\"i64\",\"name\":\"_\"}]},{\"name\":\"init\",\"type\":\"function\",\"simulate\":false,\"inputs\":[],\"outputs\":[{\"type\":\"bytes\",\"name\":\"_\"}]}],\"events\":null,\"structs\":null}" + +var TokenEventDecoder = bind.NewEventDecoder() + +func init() { +} + +type TokenContract interface { + GetBalance(opts *bind.TransactOpts) (int64, error) + + Transfer(opts *bind.TransactOpts, to common.Address, amount int64) (*bind.SyncResult, error) + TransferCommit(opts *bind.TransactOpts, to common.Address, amount int64) (*bind.CommitResult, error) + + Init(opts *bind.TransactOpts) (*bind.SyncResult, error) + InitCommit(opts *bind.TransactOpts) (*bind.CommitResult, error) +} + +type Token struct { + TokenSimulator // Read-only binding to the contract + TokenTransactor // Write-only binding to the contract +} + +type TokenSimulator struct { + contract *bind.BoundContract +} + +type TokenTransactor struct { + contract *bind.BoundContract +} + +type TokenRaw struct { + Contract *Token +} + +type TokenSimulatorRaw struct { + Contract *TokenSimulator +} + +type TokenTransactorRaw struct { + Contract *TokenTransactor +} + +func NewToken(address common.Address, backend bind.ContractBackend) (*Token, error) { + contract, err := bindToken(address, backend, backend) + if err != nil { + return nil, err + } + return &Token{TokenSimulator: TokenSimulator{contract: contract}, TokenTransactor: TokenTransactor{contract: contract}}, nil +} + +func NewTokenSimulator(address common.Address, simulator bind.ContractSimulator) (*TokenSimulator, error) { + contract, err := bindToken(address, simulator, nil) + if err != nil { + return nil, err + } + return &TokenSimulator{contract: contract}, nil +} + +func NewTokenTransactor(address common.Address, transactor bind.ContractTransactor) (*TokenTransactor, error) { + contract, err := bindToken(address, nil, transactor) + if err != nil { + return nil, err + } + return &TokenTransactor{contract: contract}, nil +} + +func bindToken(address common.Address, simulator bind.ContractSimulator, transactor bind.ContractTransactor) (*bind.BoundContract, error) { + return bind.NewBoundContract(address, simulator, transactor), nil +} + +func (_Token *TokenRaw) Transact(opts *bind.TransactOpts, fn string, params ...[]byte) (*bind.SyncResult, error) { + return _Token.Contract.TokenTransactor.contract.Transact(opts, fn, params...) +} + +func (_Token *TokenSimulatorRaw) Simulate(opts *bind.TransactOpts, fn string, params ...[]byte) (*bind.SimulateResult, error) { + return _Token.Contract.contract.Simulate(opts, fn, params...) +} + +func (_Token *TokenSimulator) GetBalance(opts *bind.TransactOpts) (int64, error) { + result, err := _Token.contract.Simulate(opts, "get_balance", bind.Args()...) + if err != nil { + return int64(0), err + } + + buf := bytes.NewBuffer(result.Data) + + var v0 int64 + binary.Read(buf, binary.BigEndian, &v0) + + return v0, nil +} + +func (_Token *TokenTransactor) Transfer(opts *bind.TransactOpts, to common.Address, amount int64) (*bind.SyncResult, error) { + return _Token.contract.Transact(opts, "transfer", bind.Args( + bind.Address(to), + bind.I64(amount))...) +} + +func (_Token *TokenTransactor) TransferCommit(opts *bind.TransactOpts, to common.Address, amount int64) (*bind.CommitResult, error) { + return _Token.contract.TransactCommit(opts, "transfer", bind.Args( + bind.Address(to), + bind.I64(amount))...) +} + +func (_Token *TokenTransactor) Init(opts *bind.TransactOpts) (*bind.SyncResult, error) { + return _Token.contract.Transact(opts, "init", bind.Args()...) +} + +func (_Token *TokenTransactor) InitCommit(opts *bind.TransactOpts) (*bind.CommitResult, error) { + return _Token.contract.TransactCommit(opts, "init", bind.Args()...) +} diff --git a/cmd/cligen/example/token.json b/cmd/cligen/example/token.json new file mode 100644 index 0000000..6bee1c0 --- /dev/null +++ b/cmd/cligen/example/token.json @@ -0,0 +1 @@ +[{"type":"function","name":"get_balance","simulate":true,"inputs":[],"outputs":[{"type":"i64","name":""}]},{"type":"function","name":"transfer","simulate":false,"inputs":[{"type":"address","name":"to"},{"type":"i64","name":"amount"}],"outputs":[{"type":"i64","name":""}]},{"type":"function","name":"init","simulate":false,"inputs":[],"outputs":[{"type":"bytes","name":""}]}] diff --git a/cmd/cligen/example/tokencmd.go b/cmd/cligen/example/tokencmd.go new file mode 100755 index 0000000..9b3e3c6 --- /dev/null +++ b/cmd/cligen/example/tokencmd.go @@ -0,0 +1,250 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package main + +import ( + "bytes" + "encoding/binary" + "encoding/json" + "errors" + "fmt" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "math/big" + "os" + "strings" + + "github.com/bluele/hypermint/abi/bind" + clibind "github.com/bluele/hypermint/cli/bind" + "github.com/bluele/hypermint/client" + "github.com/bluele/hypermint/pkg/transaction" + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/common" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = big.NewInt + _ = strings.NewReader + _ = bind.Bind + _ = clibind.Bind + _ = common.Big1 + _ = transaction.ContractInitFunc + _ = bytes.NewBuffer + _ = binary.Read + _ = json.NewEncoder +) + +func TokenCmd(contractAddress, callerAddress string) *cobra.Command { + var cmd = &cobra.Command{ + Use: "token", + Short: "token", + } + cmd.PersistentFlags().Bool("verbose", false, "verbose") + cmd.PersistentFlags().String("passphrase", "xxx", "passphrase") + cmd.PersistentFlags().String("caller", callerAddress, "caller") + cmd.PersistentFlags().String("contract", contractAddress, "contract") + cmd.PersistentFlags().String("endpoint", "tcp://localhost:26657", "endpoint") + cmd.AddCommand(tokenGetBalanceCmd) + cmd.AddCommand(tokenTransferCmd) + cmd.AddCommand(tokenInitCmd) + + return cmd +} + +func init() { +} + +var tokenGetBalanceCmd = &cobra.Command{ + Use: "get-balance", + Short: "get balance", + RunE: func(cmd *cobra.Command, args []string) error { + if err := viper.BindPFlags(cmd.Flags()); err != nil { + return err + } + verbose := viper.GetBool("verbose") + + if verbose { + fmt.Fprintf(os.Stderr, "passphrase=%v\n", viper.GetString("passphrase")) + } + + ks := clibind.NewKeyStore("keystore") + opts, c, err := tokenContractFromFlags(ks) + if err != nil { + return err + } + + if verbose { + fmt.Fprintf(os.Stderr, "simulating GetBalance...") + } + v0, err := c.GetBalance( + opts, + ) + if err != nil { + return err + } + if verbose { + fmt.Fprintf(os.Stderr, "done\n") + } + + if _, err := fmt.Fprintln(os.Stdout, v0); err != nil { + return err + } + + return nil + + }, +} + +func init() { + + cmd := tokenTransferCmd + + cmd.Flags().String("to", "", "to") + + cmd.Flags().String("amount", "", "amount") + +} + +var tokenTransferCmd = &cobra.Command{ + Use: "transfer", + Short: "transfer", + RunE: func(cmd *cobra.Command, args []string) error { + if err := viper.BindPFlags(cmd.Flags()); err != nil { + return err + } + verbose := viper.GetBool("verbose") + + if len(viper.GetString("to")) == 0 { + return errors.New("invalid address") + } + argto := common.HexToAddress(viper.GetString("to")) + + if verbose { + fmt.Fprintf(os.Stderr, "to=%v\n", argto) + } + + argamount := int64(viper.GetInt64("amount")) + + if verbose { + fmt.Fprintf(os.Stderr, "amount=%v\n", argamount) + } + + if verbose { + fmt.Fprintf(os.Stderr, "passphrase=%v\n", viper.GetString("passphrase")) + } + + ks := clibind.NewKeyStore("keystore") + opts, c, err := tokenContractFromFlags(ks) + if err != nil { + return err + } + + if verbose { + fmt.Fprintf(os.Stderr, "committing Transfer...") + } + r, err := c.TransferCommit( + opts, + argto, + argamount, + ) + if err != nil { + return err + } + if verbose { + fmt.Fprintf(os.Stderr, "%v\n", r.TxHash.Hex()) + } + ed := TokenEventDecoder + if ed == nil { + return errors.New("TokenEventDecoder is nil") + } + + return nil + + }, +} + +func init() { +} + +var tokenInitCmd = &cobra.Command{ + Use: "init", + Short: "init", + RunE: func(cmd *cobra.Command, args []string) error { + if err := viper.BindPFlags(cmd.Flags()); err != nil { + return err + } + verbose := viper.GetBool("verbose") + + if verbose { + fmt.Fprintf(os.Stderr, "passphrase=%v\n", viper.GetString("passphrase")) + } + + ks := clibind.NewKeyStore("keystore") + opts, c, err := tokenContractFromFlags(ks) + if err != nil { + return err + } + + if verbose { + fmt.Fprintf(os.Stderr, "committing Init...") + } + r, err := c.InitCommit( + opts, + ) + if err != nil { + return err + } + if verbose { + fmt.Fprintf(os.Stderr, "%v\n", r.TxHash.Hex()) + } + ed := TokenEventDecoder + if ed == nil { + return errors.New("TokenEventDecoder is nil") + } + + return nil + + }, +} + +func tokenContractFromFlags(ks *keystore.KeyStore) (*bind.TransactOpts, TokenContract, error) { + pp, err := clibind.GetFlagPassphrase(func() (string, error) { + pp := viper.GetString("passphrase") + if pp == "xxx" { + return "", errors.New("passphrase required") + } + return pp, nil + })() + if err != nil { + return nil, nil, err + } + + caller := common.HexToAddress(viper.GetString("caller")) + if err := clibind.Unlock(ks, caller, pp); err != nil { + return nil, nil, err + } + + contractAddress, err := clibind.GetFlagAddress(func() (string, error) { + return viper.GetString("contract"), nil + }, nil)() + if err != nil { + return nil, nil, err + } + + opts, err := bind.NewKeyStoreTransactor(ks, accounts.Account{Address: caller}) + if err != nil { + return nil, nil, err + } + + endpoint := viper.GetString("endpoint") + cl := client.NewClient(endpoint) + cToken, err := NewToken(contractAddress, cl) + if err != nil { + return nil, nil, err + } + + return opts, cToken, nil +} diff --git a/cmd/cligen/main.go b/cmd/cligen/main.go new file mode 100644 index 0000000..736ef31 --- /dev/null +++ b/cmd/cligen/main.go @@ -0,0 +1,5 @@ +package main + +func main() { + Execute() +} From ede48b6fc908fc28eb40ad8d5c9bfa4e9b05f37a Mon Sep 17 00:00:00 2001 From: Kiyoshi Ikehara Date: Wed, 9 Oct 2019 23:00:44 +0900 Subject: [PATCH 05/24] generate entrypoints from funcitons with arguments for the sake of code generation --- example/token/src/lib.rs | 2 +- hmcdk/genabi/Cargo.lock | 96 ++++++++++++++++++++++++++++++++ hmcdk/genabi/Cargo.toml | 15 +++++ hmcdk/genabi/README.md | 8 +++ hmcdk/genabi/src/argument.rs | 56 +++++++++++++++++++ hmcdk/genabi/src/function.rs | 105 +++++++++++++++++++++++++++++++++++ hmcdk/genabi/src/main.rs | 72 ++++++++++++++++++++++++ 7 files changed, 353 insertions(+), 1 deletion(-) create mode 100644 hmcdk/genabi/Cargo.lock create mode 100644 hmcdk/genabi/Cargo.toml create mode 100644 hmcdk/genabi/README.md create mode 100644 hmcdk/genabi/src/argument.rs create mode 100644 hmcdk/genabi/src/function.rs create mode 100644 hmcdk/genabi/src/main.rs diff --git a/example/token/src/lib.rs b/example/token/src/lib.rs index c7c5586..d07a295 100644 --- a/example/token/src/lib.rs +++ b/example/token/src/lib.rs @@ -5,7 +5,7 @@ use hmcdk::prelude::*; static TOTAL: i64 = 10000; -#[contract] +#[contract(readonly)] pub fn get_balance() -> R { Ok(Some(read_state(&get_sender()?)?)) } diff --git a/hmcdk/genabi/Cargo.lock b/hmcdk/genabi/Cargo.lock new file mode 100644 index 0000000..8a9a284 --- /dev/null +++ b/hmcdk/genabi/Cargo.lock @@ -0,0 +1,96 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "abi" +version = "0.1.0" + +[[package]] +name = "genabi" +version = "0.0.0" +dependencies = [ + "abi 0.1.0", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itoa" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro2" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ryu" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" +"checksum proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90cf5f418035b98e655e9cdb225047638296b862b42411c4e45bb88d700f7fc0" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" +"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" +"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" +"checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" +"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" diff --git a/hmcdk/genabi/Cargo.toml b/hmcdk/genabi/Cargo.toml new file mode 100644 index 0000000..162e949 --- /dev/null +++ b/hmcdk/genabi/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "genabi" +version = "0.0.0" +authors = ["Kiyoshi Nakao "] +edition = "2018" +publish = false + +[dependencies] +abi = { path = "../abi" } +syn = { version = "1.0", features = ["full", "visit"] } +quote = "1.0" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" + +[workspace] diff --git a/hmcdk/genabi/README.md b/hmcdk/genabi/README.md new file mode 100644 index 0000000..07558dc --- /dev/null +++ b/hmcdk/genabi/README.md @@ -0,0 +1,8 @@ + +This is a preliminary implementation of an ABI json generator. + +## Generating json file from a contract source + +``` +$ cargo run ../../example/token/src/lib.rs +``` diff --git a/hmcdk/genabi/src/argument.rs b/hmcdk/genabi/src/argument.rs new file mode 100644 index 0000000..8a134a7 --- /dev/null +++ b/hmcdk/genabi/src/argument.rs @@ -0,0 +1,56 @@ +use syn::{GenericArgument, PathArguments, Type}; + +use super::types; +use std::fmt; +use std::fmt::Display; + +pub enum ArgumentError { + UnrecognizedType, + UnsupportedType(String), +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +pub struct Argument { + r#type: String, + name: String, +} + +impl Display for Argument { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.r#type) + } +} + +pub fn from_name_and_type(name: &String, ty: &Type) -> Result { + match ty { + Type::Path(type_path) => { + let pair = type_path + .path + .segments + .last() + .ok_or(ArgumentError::UnrecognizedType)?; + let ident = &pair.ident; + match types::to_abi_primitive(&ident.to_string()) { + Some(x) => { + return Ok(Argument { + r#type: types::get_primitive_name(x), + name: name.clone(), + }) + } + None => match ident.to_string().as_str() { + "R" => { + return match &pair.arguments { + PathArguments::AngleBracketed(x) => match x.args.first() { + Some(GenericArgument::Type(ty)) => from_name_and_type(&name, &ty), + _ => Err(ArgumentError::UnsupportedType("R".to_string())), + }, + _ => Err(ArgumentError::UnsupportedType("R".to_string())), + } + } + _ => return Err(ArgumentError::UnsupportedType(ident.to_string())), + }, + } + } + _ => Err(ArgumentError::UnrecognizedType), + } +} diff --git a/hmcdk/genabi/src/function.rs b/hmcdk/genabi/src/function.rs new file mode 100644 index 0000000..8ea1fca --- /dev/null +++ b/hmcdk/genabi/src/function.rs @@ -0,0 +1,105 @@ +use std::ops::Deref; +use syn::visit::{self, Visit}; +use syn::{FnArg, ItemFn, Pat, ReturnType}; + +use super::argument; +use super::argument::Argument; +use super::argument::ArgumentError; + +#[derive(Clone, Serialize, Deserialize, Debug)] +pub struct Function { + r#type: String, + name: String, + simulate: bool, + inputs: Vec, + outputs: Vec, +} + +pub struct FnVisitor { + pub functions: Vec, + pub error: Option, +} + +impl<'ast> Visit<'ast> for FnVisitor { + fn visit_item_fn(&mut self, node: &'ast ItemFn) { + match from_item_fn(node) { + Ok(Some(f)) => self.functions.push(f), + Ok(None) => {} + Err(x) => self.error = Some(x), + } + visit::visit_item_fn(self, node); + } +} + +fn get_argument_from_arg(arg: &FnArg) -> Result { + match arg { + FnArg::Typed(pat_type) => match pat_type.pat.deref() { + Pat::Ident(pat) => { + let pat = &pat.ident; + return argument::from_name_and_type(&pat.to_string(), &pat_type.ty); + } + _ => Err(ArgumentError::UnrecognizedType), + }, + FnArg::Receiver(_receiver) => Err(ArgumentError::UnrecognizedType), + } +} + +fn get_return_type(rtype: &ReturnType) -> Result, ArgumentError> { + match rtype { + ReturnType::Default => Ok(None), + ReturnType::Type(_token, b) => { + match argument::from_name_and_type(&"".to_string(), b.deref()) { + Ok(a) => Ok(Some(a)), + Err(e) => Err(e), + } + } + } +} + +fn from_item_fn(f: &ItemFn) -> Result, ArgumentError> { + let mut is_contract = false; + let mut is_readonly = false; + let fn_name = f.sig.ident.to_string(); + for a in &f.attrs { + let s = a.path.segments.last(); + match s { + Some(s) => { + if s.ident == "contract" { + is_contract = true; + let ident: syn::Ident = match a.parse_args() { + Ok(ident) => ident, + Err(_) => continue + }; + if ident == "readonly" { + is_readonly = true + } + } + } + None => {} + } + } + let maybe_args = f + .sig + .inputs + .iter() + .map(|input| get_argument_from_arg(input)); + let func = match is_contract { + true => { + let rt = get_return_type(&f.sig.output)?; + let args = maybe_args.filter_map(Result::ok).collect::>(); + let f = Function { + r#type: "function".to_string(), + name: fn_name, + simulate: is_readonly, + inputs: args, + outputs: match rt { + Some(rt) => [rt].to_vec(), + None => [].to_vec(), + }, + }; + Some(f) + } + false => None, + }; + Ok(func) +} diff --git a/hmcdk/genabi/src/main.rs b/hmcdk/genabi/src/main.rs new file mode 100644 index 0000000..0b278bb --- /dev/null +++ b/hmcdk/genabi/src/main.rs @@ -0,0 +1,72 @@ +#[macro_use] +extern crate serde; +extern crate serde_json; + +use crate::Error::{ArgError, InternalError}; +use std::env; +use std::fmt::{self, Display}; +use std::fs; +use std::io::{self, Write}; +use std::path::PathBuf; +use std::process; +use syn::visit::Visit; +use syn::File; + +use abi::types; + +mod argument; +mod function; + +enum Error { + IncorrectUsage, + ArgError(argument::ArgumentError), + ReadFile(io::Error), + InternalError, +} + +impl Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use self::Error::*; + use argument::ArgumentError::*; + + match self { + IncorrectUsage => write!(f, "Usage: dump-syntax path/to/filename.rs"), + ArgError(UnrecognizedType) => write!(f, "unrecognized arg type"), + ArgError(UnsupportedType(x)) => write!(f, "unsupported arg type: {}", x), + ReadFile(error) => write!(f, "Unable to read file: {}", error), + InternalError => write!(f, "internal error"), + } + } +} + +fn main() { + if let Err(error) = try_main() { + let _ = writeln!(io::stderr(), "{}", error); + process::exit(1); + } +} + +fn try_main() -> Result<(), Error> { + let mut args = env::args_os(); + let _ = args.next(); // executable name + + let filepath = match (args.next(), args.next()) { + (Some(arg), None) => PathBuf::from(arg), + _ => return Err(Error::IncorrectUsage), + }; + + let code = fs::read_to_string(&filepath).map_err(Error::ReadFile)?; + let syntax_tree: File = syn::parse_file(&code).unwrap(); + let mut visitor = function::FnVisitor { + functions: Vec::new(), + error: None, + }; + visitor.visit_file(&syntax_tree); + match visitor.error.map(|e| ArgError(e)) { + Some(e) => return Err(e), + None => {} + } + let json = serde_json::to_string(&visitor.functions).map_err(|_x| InternalError)?; + println!("{}", json); + Ok(()) +} From 3cbc3933d9bf90369109fad14b13f344fb5befa5 Mon Sep 17 00:00:00 2001 From: Kiyoshi Ikehara Date: Wed, 9 Oct 2019 23:00:58 +0900 Subject: [PATCH 06/24] update go.mod --- go.mod | 2 ++ go.sum | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/go.mod b/go.mod index d18665c..86eaf97 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,8 @@ require ( github.com/gogo/protobuf v1.2.1 github.com/golang/protobuf v1.3.2 github.com/google/uuid v1.0.0 // indirect + github.com/iancoleman/strcase v0.0.0-20190422225806-e506e3ef7365 + github.com/immutability-io/go-ethereum-hdwallet v0.0.0-20190728144135-ecdde4803440 github.com/kr/pretty v0.1.0 github.com/mattn/go-isatty v0.0.4 github.com/mattn/go-shellwords v1.0.5 diff --git a/go.sum b/go.sum index b0b8a26..04ec162 100644 --- a/go.sum +++ b/go.sum @@ -6,15 +6,18 @@ github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/allegro/bigcache v1.2.0 h1:qDaE0QoF29wKBb3+pXFrJFy1ihe5OT9OiXhg1t85SxM= github.com/allegro/bigcache v1.2.0/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/aristanetworks/goarista v0.0.0-20180627184309-2c5933638c5e/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= github.com/aristanetworks/goarista v0.0.0-20181002214814-33151c4543a7 h1:6TQIK3K21/HnYLp+TAI6fjQ1YeH+KgLZbrFJwUjVrnQ= github.com/aristanetworks/goarista v0.0.0-20181002214814-33151c4543a7/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/btcsuite/btcd v0.0.0-20180531025944-86fed781132a/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d h1:xG8Pj6Y6J760xwETNmMzmlt38QSwz0BLp1cZ09g27uw= github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20180524032703-d4cc87b86016/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a h1:RQMUrEILyYJEoAT34XS/kLu40vC0+po/UfxrBBA4qZE= github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= @@ -34,6 +37,7 @@ github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14y github.com/etcd-io/bbolt v1.3.2/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/etcd-io/bbolt v1.3.3 h1:gSJmxrs37LgTqR/oyJBWok6k6SvXEUerFTbltIhXkBM= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= +github.com/ethereum/go-ethereum v1.8.11/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY= github.com/ethereum/go-ethereum v1.8.21 h1:ofzsxFj+zKhj1k3uVa8/MJCCptqKEh/6DXq4LwdUM4E= github.com/ethereum/go-ethereum v1.8.21/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY= github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= @@ -45,6 +49,7 @@ github.com/go-kit/kit v0.6.0 h1:wTifptAGIyIuir4bRyN4h7+kAa2a4eepLYVmRe5qqQ8= github.com/go-kit/kit v0.6.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0 h1:8HUsc87TaSWLKwrnumgC8/YconD2fJQsRJAsWaPg2ic= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-stack/stack v1.7.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= @@ -57,6 +62,7 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -70,6 +76,10 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/iancoleman/strcase v0.0.0-20190422225806-e506e3ef7365 h1:ECW73yc9MY7935nNYXUkK7Dz17YuSUI9yqRqYS8aBww= +github.com/iancoleman/strcase v0.0.0-20190422225806-e506e3ef7365/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= +github.com/immutability-io/go-ethereum-hdwallet v0.0.0-20190728144135-ecdde4803440 h1:oohLVXm39Kgf78zTdJp0ISzRu+VRSfDNt+Ec49qqrPM= +github.com/immutability-io/go-ethereum-hdwallet v0.0.0-20190728144135-ecdde4803440/go.mod h1:0P67J6Odst2b6oZrvlYkjB23Y/6cZWVQiR1Z3DbGALY= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -96,6 +106,7 @@ github.com/mattn/go-shellwords v1.0.5 h1:JhhFTIOslh5ZsPrpa3Wdg8bF0WI3b44EMblmU9w github.com/mattn/go-shellwords v1.0.5/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miguelmota/go-ethereum-hdwallet v0.0.0-20190720004541-5f6b3168e4a0/go.mod h1:VVt+rn/itmf+9eZq9CAabVlsfsHveUNUQ0bRv3ChqxY= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -153,6 +164,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/syndtr/goleveldb v0.0.0-20180621010148-0d5a0ceb10cf/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965 h1:1oFLiOyVl+W7bnBzGhf7BbIv9loSFQcieWWYIjLqcAw= github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= github.com/tendermint/go-amino v0.14.1 h1:o2WudxNfdLNBwMyl2dqOJxiro5rfrEaU0Ugs6offJMk= @@ -164,11 +176,13 @@ github.com/tendermint/tendermint v0.32.3 h1:GEnWpGQ795h5oTFNbfBLsY0LW/CW2j6p6Hti github.com/tendermint/tendermint v0.32.3/go.mod h1:ZK2c29jl1QRYznIRyRWRDsmm1yvtPzBRT00x4t1JToY= github.com/tendermint/tm-db v0.1.1 h1:G3Xezy3sOk9+ekhjZ/kjArYIs1SmwV+1OUgNkj7RgV0= github.com/tendermint/tm-db v0.1.1/go.mod h1:0cPKWu2Mou3IlxecH+MEUSYc1Ch537alLe6CpFrKzgw= +github.com/tyler-smith/go-bip39 v0.0.0-20180618194314-52158e4697b8/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/tyler-smith/go-bip39 v0.3.6 h1:HHfkwlRk4+99y7QbMS1I/tuiSE5rctNLqpeH6uUQROU= github.com/tyler-smith/go-bip39 v0.3.6/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -230,6 +244,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/karalabe/cookiejar.v2 v2.0.0-20150724131613-8dcd6a7f4951/go.mod h1:owOxCRGGeAx1uugABik6K9oeNu1cgxP/R9ItzLDxNWA= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= From 59705d9a7a52cd8725c67af9f912f46a9092a918 Mon Sep 17 00:00:00 2001 From: Kiyoshi Nakao Date: Mon, 21 Oct 2019 16:20:05 +0900 Subject: [PATCH 07/24] add hmclient package --- cmd/cligen/example/tokencmd.go | 2 +- {client => pkg/hmclient}/client.go | 8 ++++---- {client => pkg/hmclient}/error.go | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) rename {client => pkg/hmclient}/client.go (96%) rename {client => pkg/hmclient}/error.go (82%) diff --git a/cmd/cligen/example/tokencmd.go b/cmd/cligen/example/tokencmd.go index 9b3e3c6..339380b 100755 --- a/cmd/cligen/example/tokencmd.go +++ b/cmd/cligen/example/tokencmd.go @@ -240,7 +240,7 @@ func tokenContractFromFlags(ks *keystore.KeyStore) (*bind.TransactOpts, TokenCon } endpoint := viper.GetString("endpoint") - cl := client.NewClient(endpoint) + cl := hmclient.NewClient(endpoint) cToken, err := NewToken(contractAddress, cl) if err != nil { return nil, nil, err diff --git a/client/client.go b/pkg/hmclient/client.go similarity index 96% rename from client/client.go rename to pkg/hmclient/client.go index c0c2c87..a899b0c 100644 --- a/client/client.go +++ b/pkg/hmclient/client.go @@ -1,4 +1,4 @@ -package client +package hmclient import ( "context" @@ -114,9 +114,9 @@ func (c *Client) TransactionEventEntries(ctx context.Context, txHash common.Hash if err != nil { return nil, err } - tx, error := transaction.DecodeTx(resultTx.Tx) - if error != nil { - return nil, errors.New(error.Error()) + tx, err := transaction.DecodeTx(resultTx.Tx) + if err != nil { + return nil, errors.New(err.Error()) } switch tx := tx.(type) { case *transaction.ContractCallTx: diff --git a/client/error.go b/pkg/hmclient/error.go similarity index 82% rename from client/error.go rename to pkg/hmclient/error.go index ac115eb..29b95bd 100644 --- a/client/error.go +++ b/pkg/hmclient/error.go @@ -1,4 +1,4 @@ -package client +package hmclient import "errors" From afb064be7abf5f23919ffdfb613d6682d2bce0cd Mon Sep 17 00:00:00 2001 From: Kiyoshi Nakao Date: Mon, 21 Oct 2019 16:23:55 +0900 Subject: [PATCH 08/24] move packages --- {abi => pkg/account/abi}/abi.go | 0 {abi => pkg/account/abi}/argument.go | 0 {abi => pkg/account/abi}/bind/args.go | 0 {abi => pkg/account/abi}/bind/auth.go | 0 {abi => pkg/account/abi}/bind/backend.go | 0 {abi => pkg/account/abi}/bind/bind.go | 0 {abi => pkg/account/abi}/bind/bind_test.go | 0 {abi => pkg/account/abi}/bind/contract.go | 0 {abi => pkg/account/abi}/bind/event.go | 0 {abi => pkg/account/abi}/bind/event_test.go | 0 {abi => pkg/account/abi}/bind/primitives.go | 0 {abi => pkg/account/abi}/bind/template.go | 0 {abi => pkg/account/abi}/bind/transaction.go | 0 {abi => pkg/account/abi}/bind/types.go | 0 {abi => pkg/account/abi}/event.go | 0 {abi => pkg/account/abi}/function.go | 0 {abi => pkg/account/abi}/struct.go | 0 {abi => pkg/account/abi}/type.go | 0 {abi => pkg/account/abi}/types.go | 0 {cli => pkg/account/cli}/bind/auth.go | 0 {cli => pkg/account/cli}/bind/bind.go | 0 {cli => pkg/account/cli}/bind/flags.go | 0 {cli => pkg/account/cli}/bind/template.go | 0 {cli => pkg/account/cli}/bind/unlock.go | 0 {cli => pkg/account/cli}/passphrase.go | 0 25 files changed, 0 insertions(+), 0 deletions(-) rename {abi => pkg/account/abi}/abi.go (100%) rename {abi => pkg/account/abi}/argument.go (100%) rename {abi => pkg/account/abi}/bind/args.go (100%) rename {abi => pkg/account/abi}/bind/auth.go (100%) rename {abi => pkg/account/abi}/bind/backend.go (100%) rename {abi => pkg/account/abi}/bind/bind.go (100%) rename {abi => pkg/account/abi}/bind/bind_test.go (100%) rename {abi => pkg/account/abi}/bind/contract.go (100%) rename {abi => pkg/account/abi}/bind/event.go (100%) rename {abi => pkg/account/abi}/bind/event_test.go (100%) rename {abi => pkg/account/abi}/bind/primitives.go (100%) rename {abi => pkg/account/abi}/bind/template.go (100%) rename {abi => pkg/account/abi}/bind/transaction.go (100%) rename {abi => pkg/account/abi}/bind/types.go (100%) rename {abi => pkg/account/abi}/event.go (100%) rename {abi => pkg/account/abi}/function.go (100%) rename {abi => pkg/account/abi}/struct.go (100%) rename {abi => pkg/account/abi}/type.go (100%) rename {abi => pkg/account/abi}/types.go (100%) rename {cli => pkg/account/cli}/bind/auth.go (100%) rename {cli => pkg/account/cli}/bind/bind.go (100%) rename {cli => pkg/account/cli}/bind/flags.go (100%) rename {cli => pkg/account/cli}/bind/template.go (100%) rename {cli => pkg/account/cli}/bind/unlock.go (100%) rename {cli => pkg/account/cli}/passphrase.go (100%) diff --git a/abi/abi.go b/pkg/account/abi/abi.go similarity index 100% rename from abi/abi.go rename to pkg/account/abi/abi.go diff --git a/abi/argument.go b/pkg/account/abi/argument.go similarity index 100% rename from abi/argument.go rename to pkg/account/abi/argument.go diff --git a/abi/bind/args.go b/pkg/account/abi/bind/args.go similarity index 100% rename from abi/bind/args.go rename to pkg/account/abi/bind/args.go diff --git a/abi/bind/auth.go b/pkg/account/abi/bind/auth.go similarity index 100% rename from abi/bind/auth.go rename to pkg/account/abi/bind/auth.go diff --git a/abi/bind/backend.go b/pkg/account/abi/bind/backend.go similarity index 100% rename from abi/bind/backend.go rename to pkg/account/abi/bind/backend.go diff --git a/abi/bind/bind.go b/pkg/account/abi/bind/bind.go similarity index 100% rename from abi/bind/bind.go rename to pkg/account/abi/bind/bind.go diff --git a/abi/bind/bind_test.go b/pkg/account/abi/bind/bind_test.go similarity index 100% rename from abi/bind/bind_test.go rename to pkg/account/abi/bind/bind_test.go diff --git a/abi/bind/contract.go b/pkg/account/abi/bind/contract.go similarity index 100% rename from abi/bind/contract.go rename to pkg/account/abi/bind/contract.go diff --git a/abi/bind/event.go b/pkg/account/abi/bind/event.go similarity index 100% rename from abi/bind/event.go rename to pkg/account/abi/bind/event.go diff --git a/abi/bind/event_test.go b/pkg/account/abi/bind/event_test.go similarity index 100% rename from abi/bind/event_test.go rename to pkg/account/abi/bind/event_test.go diff --git a/abi/bind/primitives.go b/pkg/account/abi/bind/primitives.go similarity index 100% rename from abi/bind/primitives.go rename to pkg/account/abi/bind/primitives.go diff --git a/abi/bind/template.go b/pkg/account/abi/bind/template.go similarity index 100% rename from abi/bind/template.go rename to pkg/account/abi/bind/template.go diff --git a/abi/bind/transaction.go b/pkg/account/abi/bind/transaction.go similarity index 100% rename from abi/bind/transaction.go rename to pkg/account/abi/bind/transaction.go diff --git a/abi/bind/types.go b/pkg/account/abi/bind/types.go similarity index 100% rename from abi/bind/types.go rename to pkg/account/abi/bind/types.go diff --git a/abi/event.go b/pkg/account/abi/event.go similarity index 100% rename from abi/event.go rename to pkg/account/abi/event.go diff --git a/abi/function.go b/pkg/account/abi/function.go similarity index 100% rename from abi/function.go rename to pkg/account/abi/function.go diff --git a/abi/struct.go b/pkg/account/abi/struct.go similarity index 100% rename from abi/struct.go rename to pkg/account/abi/struct.go diff --git a/abi/type.go b/pkg/account/abi/type.go similarity index 100% rename from abi/type.go rename to pkg/account/abi/type.go diff --git a/abi/types.go b/pkg/account/abi/types.go similarity index 100% rename from abi/types.go rename to pkg/account/abi/types.go diff --git a/cli/bind/auth.go b/pkg/account/cli/bind/auth.go similarity index 100% rename from cli/bind/auth.go rename to pkg/account/cli/bind/auth.go diff --git a/cli/bind/bind.go b/pkg/account/cli/bind/bind.go similarity index 100% rename from cli/bind/bind.go rename to pkg/account/cli/bind/bind.go diff --git a/cli/bind/flags.go b/pkg/account/cli/bind/flags.go similarity index 100% rename from cli/bind/flags.go rename to pkg/account/cli/bind/flags.go diff --git a/cli/bind/template.go b/pkg/account/cli/bind/template.go similarity index 100% rename from cli/bind/template.go rename to pkg/account/cli/bind/template.go diff --git a/cli/bind/unlock.go b/pkg/account/cli/bind/unlock.go similarity index 100% rename from cli/bind/unlock.go rename to pkg/account/cli/bind/unlock.go diff --git a/cli/passphrase.go b/pkg/account/cli/passphrase.go similarity index 100% rename from cli/passphrase.go rename to pkg/account/cli/passphrase.go From 36a2c2411ebbf42f7ac4a4ed66485c29608fb082 Mon Sep 17 00:00:00 2001 From: Kiyoshi Nakao Date: Mon, 21 Oct 2019 16:38:15 +0900 Subject: [PATCH 09/24] fix imports --- Makefile | 10 ++++++++++ cmd/abigen/cmd.go | 2 +- cmd/abigen/example/token.go | 2 +- cmd/cligen/cmd.go | 4 ++-- cmd/cligen/example/token.go | 2 +- cmd/cligen/example/tokencmd.go | 6 +++--- pkg/account/abi/bind/bind.go | 2 +- pkg/account/abi/bind/template.go | 2 +- pkg/account/cli/bind/bind.go | 2 +- pkg/account/cli/bind/flags.go | 2 +- pkg/account/cli/bind/template.go | 6 +++--- pkg/hmclient/client.go | 2 +- 12 files changed, 26 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index 1607aa2..b204f38 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,8 @@ GO_BIN?=go BUILD_DIR?=./build HMD?=$(BUILD_DIR)/hmd HMCLI?=$(BUILD_DIR)/hmcli +ABIGEN?=$(BUILD_DIR)/abigen +CLIGEN?=$(BUILD_DIR)/cligen HMD_HOME?=${HOME}/.hmd HMCLI_HOME?=${HOME}/.hmcli @@ -30,9 +32,17 @@ server: cli: $(GO_BUILD_CMD) -o $(HMCLI) ./cmd/hmcli +abigen: + $(GO_BUILD_CMD) -o $(ABIGEN) ./cmd/abigen + +cligen: + $(GO_BUILD_CMD) -o $(CLIGEN) ./cmd/cligen + release-build: $(GO_BUILD_CMD) -o $(HMD)_$(GOOS)_$(GOARCH) ./cmd/hmd $(GO_BUILD_CMD) -o $(HMCLI)_$(GOOS)_$(GOARCH) ./cmd/hmcli + $(GO_BUILD_CMD) -o $(ABIGEN)_$(GOOS)_$(GOARCH) ./cmd/abigen + $(GO_BUILD_CMD) -o $(CLIGEN)_$(GOOS)_$(GOARCH) ./cmd/cligen fmt: cd ./hmc && cargo fmt diff --git a/cmd/abigen/cmd.go b/cmd/abigen/cmd.go index 44f7499..0d41f78 100644 --- a/cmd/abigen/cmd.go +++ b/cmd/abigen/cmd.go @@ -3,13 +3,13 @@ package main import ( "errors" "fmt" + "github.com/bluele/hypermint/pkg/account/abi/bind" "github.com/spf13/cobra" "github.com/spf13/viper" "io/ioutil" "os" "path" "strings" - "github.com/bluele/hypermint/abi/bind" ) var rootCmd = &cobra.Command{ diff --git a/cmd/abigen/example/token.go b/cmd/abigen/example/token.go index 4466073..47b0117 100755 --- a/cmd/abigen/example/token.go +++ b/cmd/abigen/example/token.go @@ -8,7 +8,7 @@ import ( "encoding/binary" "encoding/json" - "github.com/bluele/hypermint/abi/bind" + "github.com/bluele/hypermint/pkg/account/abi/bind" "github.com/bluele/hypermint/pkg/transaction" "github.com/ethereum/go-ethereum/common" diff --git a/cmd/cligen/cmd.go b/cmd/cligen/cmd.go index a78ecbb..4b09698 100644 --- a/cmd/cligen/cmd.go +++ b/cmd/cligen/cmd.go @@ -3,8 +3,8 @@ package main import ( "errors" "fmt" - "github.com/bluele/hypermint/abi/bind" - clibind "github.com/bluele/hypermint/cli/bind" + "github.com/bluele/hypermint/pkg/account/abi/bind" + clibind "github.com/bluele/hypermint/pkg/account/cli/bind" "github.com/spf13/cobra" "github.com/spf13/viper" "io/ioutil" diff --git a/cmd/cligen/example/token.go b/cmd/cligen/example/token.go index e430e53..d0903bd 100755 --- a/cmd/cligen/example/token.go +++ b/cmd/cligen/example/token.go @@ -8,7 +8,7 @@ import ( "encoding/binary" "encoding/json" - "github.com/bluele/hypermint/abi/bind" + "github.com/bluele/hypermint/pkg/account/abi/bind" "github.com/bluele/hypermint/pkg/transaction" "github.com/ethereum/go-ethereum/common" ) diff --git a/cmd/cligen/example/tokencmd.go b/cmd/cligen/example/tokencmd.go index 339380b..46b42ce 100755 --- a/cmd/cligen/example/tokencmd.go +++ b/cmd/cligen/example/tokencmd.go @@ -15,9 +15,9 @@ import ( "os" "strings" - "github.com/bluele/hypermint/abi/bind" - clibind "github.com/bluele/hypermint/cli/bind" - "github.com/bluele/hypermint/client" + "github.com/bluele/hypermint/pkg/account/abi/bind" + clibind "github.com/bluele/hypermint/pkg/account/cli/bind" + "github.com/bluele/hypermint/pkg/account/client" "github.com/bluele/hypermint/pkg/transaction" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/keystore" diff --git a/pkg/account/abi/bind/bind.go b/pkg/account/abi/bind/bind.go index 22141ff..7fe4f3f 100644 --- a/pkg/account/abi/bind/bind.go +++ b/pkg/account/abi/bind/bind.go @@ -4,7 +4,7 @@ import ( "bytes" "encoding/json" "fmt" - "github.com/bluele/hypermint/abi" + "github.com/bluele/hypermint/pkg/account/abi" "github.com/iancoleman/strcase" "go/format" "strings" diff --git a/pkg/account/abi/bind/template.go b/pkg/account/abi/bind/template.go index 7e5961f..e84a9be 100644 --- a/pkg/account/abi/bind/template.go +++ b/pkg/account/abi/bind/template.go @@ -11,7 +11,7 @@ import ( "bytes" "encoding/json" - "github.com/bluele/hypermint/abi/bind" + "github.com/bluele/hypermint/pkg/account/abi/bind" "github.com/bluele/hypermint/pkg/transaction" "github.com/ethereum/go-ethereum/common" {{if .Mock}} diff --git a/pkg/account/cli/bind/bind.go b/pkg/account/cli/bind/bind.go index a68b7ba..ed1ac9a 100644 --- a/pkg/account/cli/bind/bind.go +++ b/pkg/account/cli/bind/bind.go @@ -4,7 +4,7 @@ import ( "bytes" "encoding/json" "fmt" - "github.com/bluele/hypermint/abi" + "github.com/bluele/hypermint/pkg/account/abi" "github.com/iancoleman/strcase" "go/format" "strings" diff --git a/pkg/account/cli/bind/flags.go b/pkg/account/cli/bind/flags.go index 77e5269..8f22f21 100644 --- a/pkg/account/cli/bind/flags.go +++ b/pkg/account/cli/bind/flags.go @@ -2,7 +2,7 @@ package bind import ( "fmt" - "github.com/bluele/hypermint/cli" + "github.com/bluele/hypermint/pkg/account/cli" "github.com/ethereum/go-ethereum/common" ) diff --git a/pkg/account/cli/bind/template.go b/pkg/account/cli/bind/template.go index 1160f44..148e8f2 100644 --- a/pkg/account/cli/bind/template.go +++ b/pkg/account/cli/bind/template.go @@ -18,9 +18,9 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/bluele/hypermint/abi/bind" - clibind "github.com/bluele/hypermint/cli/bind" - "github.com/bluele/hypermint/client" + "github.com/bluele/hypermint/pkg/account/abi/bind" + clibind "github.com/bluele/hypermint/pkg/account/cli/bind" + "github.com/bluele/hypermint/pkg/account/client" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/accounts" "github.com/bluele/hypermint/pkg/transaction" diff --git a/pkg/hmclient/client.go b/pkg/hmclient/client.go index a899b0c..dbdccc9 100644 --- a/pkg/hmclient/client.go +++ b/pkg/hmclient/client.go @@ -4,7 +4,7 @@ import ( "context" "github.com/bluele/hypermint/pkg/abci/codec" hmabcitypes "github.com/bluele/hypermint/pkg/abci/types" - "github.com/bluele/hypermint/abi/bind" + "github.com/bluele/hypermint/pkg/account/abi/bind" "github.com/bluele/hypermint/pkg/contract/event" "github.com/bluele/hypermint/pkg/handler" "github.com/bluele/hypermint/pkg/transaction" From f0c21d874be95de04cfb424617c394022c4338b2 Mon Sep 17 00:00:00 2001 From: Kiyoshi Nakao Date: Mon, 21 Oct 2019 16:43:12 +0900 Subject: [PATCH 10/24] remove generated code --- cmd/abigen/example/token.go | 167 ---------------------------------- cmd/abigen/example/token.json | 1 - 2 files changed, 168 deletions(-) delete mode 100755 cmd/abigen/example/token.go delete mode 100644 cmd/abigen/example/token.json diff --git a/cmd/abigen/example/token.go b/cmd/abigen/example/token.go deleted file mode 100755 index 47b0117..0000000 --- a/cmd/abigen/example/token.go +++ /dev/null @@ -1,167 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package main - -import ( - "bytes" - "encoding/binary" - "encoding/json" - - "github.com/bluele/hypermint/pkg/account/abi/bind" - "github.com/bluele/hypermint/pkg/transaction" - "github.com/ethereum/go-ethereum/common" - - "github.com/stretchr/testify/mock" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = bind.Bind - _ = common.Big1 - _ = transaction.ContractInitFunc - _ = bytes.NewBuffer - _ = binary.Read - _ = json.NewEncoder -) - -var TokenABI string = "{\"functions\":[{\"name\":\"get_balance\",\"type\":\"function\",\"simulate\":true,\"inputs\":[],\"outputs\":[{\"type\":\"i64\",\"name\":\"_\"}]},{\"name\":\"transfer\",\"type\":\"function\",\"simulate\":false,\"inputs\":[{\"type\":\"address\",\"name\":\"to\"},{\"type\":\"i64\",\"name\":\"amount\"}],\"outputs\":[{\"type\":\"i64\",\"name\":\"_\"}]},{\"name\":\"init\",\"type\":\"function\",\"simulate\":false,\"inputs\":[],\"outputs\":[{\"type\":\"bytes\",\"name\":\"_\"}]}],\"events\":null,\"structs\":null}" - -var TokenEventDecoder = bind.NewEventDecoder() - -func init() { -} - -type TokenContract interface { - GetBalance(opts *bind.TransactOpts) (int64, error) - - Transfer(opts *bind.TransactOpts, to common.Address, amount int64) (*bind.SyncResult, error) - TransferCommit(opts *bind.TransactOpts, to common.Address, amount int64) (*bind.CommitResult, error) - - Init(opts *bind.TransactOpts) (*bind.SyncResult, error) - InitCommit(opts *bind.TransactOpts) (*bind.CommitResult, error) -} - -type Token struct { - TokenSimulator // Read-only binding to the contract - TokenTransactor // Write-only binding to the contract -} - -type TokenSimulator struct { - contract *bind.BoundContract -} - -type TokenTransactor struct { - contract *bind.BoundContract -} - -type TokenRaw struct { - Contract *Token -} - -type TokenSimulatorRaw struct { - Contract *TokenSimulator -} - -type TokenTransactorRaw struct { - Contract *TokenTransactor -} - -func NewToken(address common.Address, backend bind.ContractBackend) (*Token, error) { - contract, err := bindToken(address, backend, backend) - if err != nil { - return nil, err - } - return &Token{TokenSimulator: TokenSimulator{contract: contract}, TokenTransactor: TokenTransactor{contract: contract}}, nil -} - -func NewTokenSimulator(address common.Address, simulator bind.ContractSimulator) (*TokenSimulator, error) { - contract, err := bindToken(address, simulator, nil) - if err != nil { - return nil, err - } - return &TokenSimulator{contract: contract}, nil -} - -func NewTokenTransactor(address common.Address, transactor bind.ContractTransactor) (*TokenTransactor, error) { - contract, err := bindToken(address, nil, transactor) - if err != nil { - return nil, err - } - return &TokenTransactor{contract: contract}, nil -} - -func bindToken(address common.Address, simulator bind.ContractSimulator, transactor bind.ContractTransactor) (*bind.BoundContract, error) { - return bind.NewBoundContract(address, simulator, transactor), nil -} - -func (_Token *TokenRaw) Transact(opts *bind.TransactOpts, fn string, params ...[]byte) (*bind.SyncResult, error) { - return _Token.Contract.TokenTransactor.contract.Transact(opts, fn, params...) -} - -func (_Token *TokenSimulatorRaw) Simulate(opts *bind.TransactOpts, fn string, params ...[]byte) (*bind.SimulateResult, error) { - return _Token.Contract.contract.Simulate(opts, fn, params...) -} - -func (_Token *TokenSimulator) GetBalance(opts *bind.TransactOpts) (int64, error) { - result, err := _Token.contract.Simulate(opts, "get_balance", bind.Args()...) - if err != nil { - return int64(0), err - } - - buf := bytes.NewBuffer(result.Data) - - var v0 int64 - binary.Read(buf, binary.BigEndian, &v0) - - return v0, nil -} - -func (_Token *TokenTransactor) Transfer(opts *bind.TransactOpts, to common.Address, amount int64) (*bind.SyncResult, error) { - return _Token.contract.Transact(opts, "transfer", bind.Args( - bind.Address(to), - bind.I64(amount))...) -} - -func (_Token *TokenTransactor) TransferCommit(opts *bind.TransactOpts, to common.Address, amount int64) (*bind.CommitResult, error) { - return _Token.contract.TransactCommit(opts, "transfer", bind.Args( - bind.Address(to), - bind.I64(amount))...) -} - -func (_Token *TokenTransactor) Init(opts *bind.TransactOpts) (*bind.SyncResult, error) { - return _Token.contract.Transact(opts, "init", bind.Args()...) -} - -func (_Token *TokenTransactor) InitCommit(opts *bind.TransactOpts) (*bind.CommitResult, error) { - return _Token.contract.TransactCommit(opts, "init", bind.Args()...) -} - -type MockToken struct { - mock.Mock -} - -func (_Token *MockToken) GetBalance(opts *bind.TransactOpts) (int64, error) { - ret := _Token.Called() - return ret.Get(0).(int64), ret.Error(1) -} - -func (_Token *MockToken) Transfer(opts *bind.TransactOpts, to common.Address, amount int64) (*bind.SyncResult, error) { - ret := _Token.Called(to, amount) - return ret.Get(0).(*bind.SyncResult), ret.Error(1) -} - -func (_Token *MockToken) TransferCommit(opts *bind.TransactOpts, to common.Address, amount int64) (*bind.CommitResult, error) { - ret := _Token.Called(to, amount) - return ret.Get(0).(*bind.CommitResult), ret.Error(1) -} - -func (_Token *MockToken) Init(opts *bind.TransactOpts) (*bind.SyncResult, error) { - ret := _Token.Called() - return ret.Get(0).(*bind.SyncResult), ret.Error(1) -} - -func (_Token *MockToken) InitCommit(opts *bind.TransactOpts) (*bind.CommitResult, error) { - ret := _Token.Called() - return ret.Get(0).(*bind.CommitResult), ret.Error(1) -} diff --git a/cmd/abigen/example/token.json b/cmd/abigen/example/token.json deleted file mode 100644 index 6bee1c0..0000000 --- a/cmd/abigen/example/token.json +++ /dev/null @@ -1 +0,0 @@ -[{"type":"function","name":"get_balance","simulate":true,"inputs":[],"outputs":[{"type":"i64","name":""}]},{"type":"function","name":"transfer","simulate":false,"inputs":[{"type":"address","name":"to"},{"type":"i64","name":"amount"}],"outputs":[{"type":"i64","name":""}]},{"type":"function","name":"init","simulate":false,"inputs":[],"outputs":[{"type":"bytes","name":""}]}] From 4a6095e1660f401c1e8e11f7f4db4bfdb2f438c5 Mon Sep 17 00:00:00 2001 From: Kiyoshi Nakao Date: Mon, 21 Oct 2019 16:51:35 +0900 Subject: [PATCH 11/24] fix template --- cmd/cligen/.gitignore | 3 + cmd/cligen/Makefile | 2 +- cmd/cligen/example/token.go | 136 ----------------- cmd/cligen/example/token.json | 1 - cmd/cligen/example/tokencmd.go | 250 ------------------------------- pkg/account/cli/bind/template.go | 4 +- 6 files changed, 6 insertions(+), 390 deletions(-) delete mode 100755 cmd/cligen/example/token.go delete mode 100644 cmd/cligen/example/token.json delete mode 100755 cmd/cligen/example/tokencmd.go diff --git a/cmd/cligen/.gitignore b/cmd/cligen/.gitignore index 0e28463..ae65203 100644 --- a/cmd/cligen/.gitignore +++ b/cmd/cligen/.gitignore @@ -1 +1,4 @@ cligen +example/token*.go +example/*.json +example/example diff --git a/cmd/cligen/Makefile b/cmd/cligen/Makefile index e564ac5..ef174a6 100644 --- a/cmd/cligen/Makefile +++ b/cmd/cligen/Makefile @@ -1,6 +1,6 @@ .PHONY: test -test: +test: gen-example go build ./cligen --outdir example --name token --package main --abi example/token.json (cd example && go build) diff --git a/cmd/cligen/example/token.go b/cmd/cligen/example/token.go deleted file mode 100755 index d0903bd..0000000 --- a/cmd/cligen/example/token.go +++ /dev/null @@ -1,136 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package main - -import ( - "bytes" - "encoding/binary" - "encoding/json" - - "github.com/bluele/hypermint/pkg/account/abi/bind" - "github.com/bluele/hypermint/pkg/transaction" - "github.com/ethereum/go-ethereum/common" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = bind.Bind - _ = common.Big1 - _ = transaction.ContractInitFunc - _ = bytes.NewBuffer - _ = binary.Read - _ = json.NewEncoder -) - -var TokenABI string = "{\"functions\":[{\"name\":\"get_balance\",\"type\":\"function\",\"simulate\":true,\"inputs\":[],\"outputs\":[{\"type\":\"i64\",\"name\":\"_\"}]},{\"name\":\"transfer\",\"type\":\"function\",\"simulate\":false,\"inputs\":[{\"type\":\"address\",\"name\":\"to\"},{\"type\":\"i64\",\"name\":\"amount\"}],\"outputs\":[{\"type\":\"i64\",\"name\":\"_\"}]},{\"name\":\"init\",\"type\":\"function\",\"simulate\":false,\"inputs\":[],\"outputs\":[{\"type\":\"bytes\",\"name\":\"_\"}]}],\"events\":null,\"structs\":null}" - -var TokenEventDecoder = bind.NewEventDecoder() - -func init() { -} - -type TokenContract interface { - GetBalance(opts *bind.TransactOpts) (int64, error) - - Transfer(opts *bind.TransactOpts, to common.Address, amount int64) (*bind.SyncResult, error) - TransferCommit(opts *bind.TransactOpts, to common.Address, amount int64) (*bind.CommitResult, error) - - Init(opts *bind.TransactOpts) (*bind.SyncResult, error) - InitCommit(opts *bind.TransactOpts) (*bind.CommitResult, error) -} - -type Token struct { - TokenSimulator // Read-only binding to the contract - TokenTransactor // Write-only binding to the contract -} - -type TokenSimulator struct { - contract *bind.BoundContract -} - -type TokenTransactor struct { - contract *bind.BoundContract -} - -type TokenRaw struct { - Contract *Token -} - -type TokenSimulatorRaw struct { - Contract *TokenSimulator -} - -type TokenTransactorRaw struct { - Contract *TokenTransactor -} - -func NewToken(address common.Address, backend bind.ContractBackend) (*Token, error) { - contract, err := bindToken(address, backend, backend) - if err != nil { - return nil, err - } - return &Token{TokenSimulator: TokenSimulator{contract: contract}, TokenTransactor: TokenTransactor{contract: contract}}, nil -} - -func NewTokenSimulator(address common.Address, simulator bind.ContractSimulator) (*TokenSimulator, error) { - contract, err := bindToken(address, simulator, nil) - if err != nil { - return nil, err - } - return &TokenSimulator{contract: contract}, nil -} - -func NewTokenTransactor(address common.Address, transactor bind.ContractTransactor) (*TokenTransactor, error) { - contract, err := bindToken(address, nil, transactor) - if err != nil { - return nil, err - } - return &TokenTransactor{contract: contract}, nil -} - -func bindToken(address common.Address, simulator bind.ContractSimulator, transactor bind.ContractTransactor) (*bind.BoundContract, error) { - return bind.NewBoundContract(address, simulator, transactor), nil -} - -func (_Token *TokenRaw) Transact(opts *bind.TransactOpts, fn string, params ...[]byte) (*bind.SyncResult, error) { - return _Token.Contract.TokenTransactor.contract.Transact(opts, fn, params...) -} - -func (_Token *TokenSimulatorRaw) Simulate(opts *bind.TransactOpts, fn string, params ...[]byte) (*bind.SimulateResult, error) { - return _Token.Contract.contract.Simulate(opts, fn, params...) -} - -func (_Token *TokenSimulator) GetBalance(opts *bind.TransactOpts) (int64, error) { - result, err := _Token.contract.Simulate(opts, "get_balance", bind.Args()...) - if err != nil { - return int64(0), err - } - - buf := bytes.NewBuffer(result.Data) - - var v0 int64 - binary.Read(buf, binary.BigEndian, &v0) - - return v0, nil -} - -func (_Token *TokenTransactor) Transfer(opts *bind.TransactOpts, to common.Address, amount int64) (*bind.SyncResult, error) { - return _Token.contract.Transact(opts, "transfer", bind.Args( - bind.Address(to), - bind.I64(amount))...) -} - -func (_Token *TokenTransactor) TransferCommit(opts *bind.TransactOpts, to common.Address, amount int64) (*bind.CommitResult, error) { - return _Token.contract.TransactCommit(opts, "transfer", bind.Args( - bind.Address(to), - bind.I64(amount))...) -} - -func (_Token *TokenTransactor) Init(opts *bind.TransactOpts) (*bind.SyncResult, error) { - return _Token.contract.Transact(opts, "init", bind.Args()...) -} - -func (_Token *TokenTransactor) InitCommit(opts *bind.TransactOpts) (*bind.CommitResult, error) { - return _Token.contract.TransactCommit(opts, "init", bind.Args()...) -} diff --git a/cmd/cligen/example/token.json b/cmd/cligen/example/token.json deleted file mode 100644 index 6bee1c0..0000000 --- a/cmd/cligen/example/token.json +++ /dev/null @@ -1 +0,0 @@ -[{"type":"function","name":"get_balance","simulate":true,"inputs":[],"outputs":[{"type":"i64","name":""}]},{"type":"function","name":"transfer","simulate":false,"inputs":[{"type":"address","name":"to"},{"type":"i64","name":"amount"}],"outputs":[{"type":"i64","name":""}]},{"type":"function","name":"init","simulate":false,"inputs":[],"outputs":[{"type":"bytes","name":""}]}] diff --git a/cmd/cligen/example/tokencmd.go b/cmd/cligen/example/tokencmd.go deleted file mode 100755 index 46b42ce..0000000 --- a/cmd/cligen/example/tokencmd.go +++ /dev/null @@ -1,250 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package main - -import ( - "bytes" - "encoding/binary" - "encoding/json" - "errors" - "fmt" - "github.com/spf13/cobra" - "github.com/spf13/viper" - "math/big" - "os" - "strings" - - "github.com/bluele/hypermint/pkg/account/abi/bind" - clibind "github.com/bluele/hypermint/pkg/account/cli/bind" - "github.com/bluele/hypermint/pkg/account/client" - "github.com/bluele/hypermint/pkg/transaction" - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/common" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = big.NewInt - _ = strings.NewReader - _ = bind.Bind - _ = clibind.Bind - _ = common.Big1 - _ = transaction.ContractInitFunc - _ = bytes.NewBuffer - _ = binary.Read - _ = json.NewEncoder -) - -func TokenCmd(contractAddress, callerAddress string) *cobra.Command { - var cmd = &cobra.Command{ - Use: "token", - Short: "token", - } - cmd.PersistentFlags().Bool("verbose", false, "verbose") - cmd.PersistentFlags().String("passphrase", "xxx", "passphrase") - cmd.PersistentFlags().String("caller", callerAddress, "caller") - cmd.PersistentFlags().String("contract", contractAddress, "contract") - cmd.PersistentFlags().String("endpoint", "tcp://localhost:26657", "endpoint") - cmd.AddCommand(tokenGetBalanceCmd) - cmd.AddCommand(tokenTransferCmd) - cmd.AddCommand(tokenInitCmd) - - return cmd -} - -func init() { -} - -var tokenGetBalanceCmd = &cobra.Command{ - Use: "get-balance", - Short: "get balance", - RunE: func(cmd *cobra.Command, args []string) error { - if err := viper.BindPFlags(cmd.Flags()); err != nil { - return err - } - verbose := viper.GetBool("verbose") - - if verbose { - fmt.Fprintf(os.Stderr, "passphrase=%v\n", viper.GetString("passphrase")) - } - - ks := clibind.NewKeyStore("keystore") - opts, c, err := tokenContractFromFlags(ks) - if err != nil { - return err - } - - if verbose { - fmt.Fprintf(os.Stderr, "simulating GetBalance...") - } - v0, err := c.GetBalance( - opts, - ) - if err != nil { - return err - } - if verbose { - fmt.Fprintf(os.Stderr, "done\n") - } - - if _, err := fmt.Fprintln(os.Stdout, v0); err != nil { - return err - } - - return nil - - }, -} - -func init() { - - cmd := tokenTransferCmd - - cmd.Flags().String("to", "", "to") - - cmd.Flags().String("amount", "", "amount") - -} - -var tokenTransferCmd = &cobra.Command{ - Use: "transfer", - Short: "transfer", - RunE: func(cmd *cobra.Command, args []string) error { - if err := viper.BindPFlags(cmd.Flags()); err != nil { - return err - } - verbose := viper.GetBool("verbose") - - if len(viper.GetString("to")) == 0 { - return errors.New("invalid address") - } - argto := common.HexToAddress(viper.GetString("to")) - - if verbose { - fmt.Fprintf(os.Stderr, "to=%v\n", argto) - } - - argamount := int64(viper.GetInt64("amount")) - - if verbose { - fmt.Fprintf(os.Stderr, "amount=%v\n", argamount) - } - - if verbose { - fmt.Fprintf(os.Stderr, "passphrase=%v\n", viper.GetString("passphrase")) - } - - ks := clibind.NewKeyStore("keystore") - opts, c, err := tokenContractFromFlags(ks) - if err != nil { - return err - } - - if verbose { - fmt.Fprintf(os.Stderr, "committing Transfer...") - } - r, err := c.TransferCommit( - opts, - argto, - argamount, - ) - if err != nil { - return err - } - if verbose { - fmt.Fprintf(os.Stderr, "%v\n", r.TxHash.Hex()) - } - ed := TokenEventDecoder - if ed == nil { - return errors.New("TokenEventDecoder is nil") - } - - return nil - - }, -} - -func init() { -} - -var tokenInitCmd = &cobra.Command{ - Use: "init", - Short: "init", - RunE: func(cmd *cobra.Command, args []string) error { - if err := viper.BindPFlags(cmd.Flags()); err != nil { - return err - } - verbose := viper.GetBool("verbose") - - if verbose { - fmt.Fprintf(os.Stderr, "passphrase=%v\n", viper.GetString("passphrase")) - } - - ks := clibind.NewKeyStore("keystore") - opts, c, err := tokenContractFromFlags(ks) - if err != nil { - return err - } - - if verbose { - fmt.Fprintf(os.Stderr, "committing Init...") - } - r, err := c.InitCommit( - opts, - ) - if err != nil { - return err - } - if verbose { - fmt.Fprintf(os.Stderr, "%v\n", r.TxHash.Hex()) - } - ed := TokenEventDecoder - if ed == nil { - return errors.New("TokenEventDecoder is nil") - } - - return nil - - }, -} - -func tokenContractFromFlags(ks *keystore.KeyStore) (*bind.TransactOpts, TokenContract, error) { - pp, err := clibind.GetFlagPassphrase(func() (string, error) { - pp := viper.GetString("passphrase") - if pp == "xxx" { - return "", errors.New("passphrase required") - } - return pp, nil - })() - if err != nil { - return nil, nil, err - } - - caller := common.HexToAddress(viper.GetString("caller")) - if err := clibind.Unlock(ks, caller, pp); err != nil { - return nil, nil, err - } - - contractAddress, err := clibind.GetFlagAddress(func() (string, error) { - return viper.GetString("contract"), nil - }, nil)() - if err != nil { - return nil, nil, err - } - - opts, err := bind.NewKeyStoreTransactor(ks, accounts.Account{Address: caller}) - if err != nil { - return nil, nil, err - } - - endpoint := viper.GetString("endpoint") - cl := hmclient.NewClient(endpoint) - cToken, err := NewToken(contractAddress, cl) - if err != nil { - return nil, nil, err - } - - return opts, cToken, nil -} diff --git a/pkg/account/cli/bind/template.go b/pkg/account/cli/bind/template.go index 148e8f2..9fbe3fe 100644 --- a/pkg/account/cli/bind/template.go +++ b/pkg/account/cli/bind/template.go @@ -20,7 +20,7 @@ import ( "github.com/bluele/hypermint/pkg/account/abi/bind" clibind "github.com/bluele/hypermint/pkg/account/cli/bind" - "github.com/bluele/hypermint/pkg/account/client" + "github.com/bluele/hypermint/pkg/hmclient" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/accounts" "github.com/bluele/hypermint/pkg/transaction" @@ -211,7 +211,7 @@ var ( } endpoint := viper.GetString("endpoint") - cl := client.NewClient(endpoint) + cl := hmclient.NewClient(endpoint) c{{.Type}}, err := New{{.Type}}(contractAddress, cl) if err != nil { return nil, nil, err From f707a5db487b95d205c651e147186b35ab98c023 Mon Sep 17 00:00:00 2001 From: Kiyoshi Nakao Date: Mon, 21 Oct 2019 16:53:42 +0900 Subject: [PATCH 12/24] fix abigen --- cmd/abigen/cmd.go | 68 --------------------------------------- cmd/abigen/cmd_test.go | 10 ------ cmd/abigen/main.go | 65 ++++++++++++++++++++++++++++++++++++- cmd/cligen/cmd.go | 73 ------------------------------------------ cmd/cligen/main.go | 70 +++++++++++++++++++++++++++++++++++++++- 5 files changed, 133 insertions(+), 153 deletions(-) delete mode 100644 cmd/abigen/cmd.go delete mode 100644 cmd/abigen/cmd_test.go delete mode 100644 cmd/cligen/cmd.go diff --git a/cmd/abigen/cmd.go b/cmd/abigen/cmd.go deleted file mode 100644 index 0d41f78..0000000 --- a/cmd/abigen/cmd.go +++ /dev/null @@ -1,68 +0,0 @@ -package main - -import ( - "errors" - "fmt" - "github.com/bluele/hypermint/pkg/account/abi/bind" - "github.com/spf13/cobra" - "github.com/spf13/viper" - "io/ioutil" - "os" - "path" - "strings" -) - -var rootCmd = &cobra.Command{ - Use: "abigen", - Short: "Code generation from ABI", - RunE: func(cmd *cobra.Command, args []string) error { - if err := viper.BindPFlags(cmd.Flags()); err != nil { - return err - } - pkg := viper.GetString("package") - outdir := viper.GetString("outdir") - if len(outdir) == 0 { - outdir = pkg - } - name := viper.GetString("name") - if len(name) == 0 { - return errors.New("name not specified") - } - abi := viper.GetString("abi") - mock := viper.GetBool("mock") - return Generate(outdir, pkg, name, abi, mock) - }, -} - -func Generate(outdir, pkg, name, abiJsonFilename string, mock bool) error { - if abiJson, err := ioutil.ReadFile(abiJsonFilename); err != nil { - return err - } else if src, err := bind.Bind(pkg, name, string(abiJson), mock); err != nil { - return err - } else { - if err := os.MkdirAll(pkg, 0700); err != nil { - return err - } - if err := ioutil.WriteFile(path.Join(outdir, name+".go"), []byte(src), 0700); err != nil { - return err - } - return nil - } -} - -func init() { - rootCmd.Flags().String("package", "contract", "package name") - rootCmd.Flags().String("name", "", "contract name") - rootCmd.Flags().String("abi", "example.json", "abi json") - rootCmd.Flags().String("outdir", "", "output dir") - rootCmd.Flags().Bool("mock", false, "generate mock") - viper.AutomaticEnv() - viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) -} - -func Execute() { - if err := rootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(1) - } -} diff --git a/cmd/abigen/cmd_test.go b/cmd/abigen/cmd_test.go deleted file mode 100644 index 6d8eb66..0000000 --- a/cmd/abigen/cmd_test.go +++ /dev/null @@ -1,10 +0,0 @@ -package main - -import "testing" - -func TestGenerate(t *testing.T) { - err := Generate("example", "main", "token", "example/token.json", true) - if err != nil { - t.Error(err) - } -} diff --git a/cmd/abigen/main.go b/cmd/abigen/main.go index 736ef31..d6bc2c0 100644 --- a/cmd/abigen/main.go +++ b/cmd/abigen/main.go @@ -1,5 +1,68 @@ package main +import ( + "errors" + "fmt" + "github.com/bluele/hypermint/pkg/account/abi/bind" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "io/ioutil" + "os" + "path" + "strings" +) + +var rootCmd = &cobra.Command{ + Use: "abigen", + Short: "Code generation from ABI", + RunE: func(cmd *cobra.Command, args []string) error { + if err := viper.BindPFlags(cmd.Flags()); err != nil { + return err + } + pkg := viper.GetString("package") + outdir := viper.GetString("outdir") + if len(outdir) == 0 { + outdir = pkg + } + name := viper.GetString("name") + if len(name) == 0 { + return errors.New("name not specified") + } + abi := viper.GetString("abi") + mock := viper.GetBool("mock") + return Generate(outdir, pkg, name, abi, mock) + }, +} + +func Generate(outdir, pkg, name, abiJsonFilename string, mock bool) error { + if abiJson, err := ioutil.ReadFile(abiJsonFilename); err != nil { + return err + } else if src, err := bind.Bind(pkg, name, string(abiJson), mock); err != nil { + return err + } else { + if err := os.MkdirAll(pkg, 0700); err != nil { + return err + } + if err := ioutil.WriteFile(path.Join(outdir, name+".go"), []byte(src), 0700); err != nil { + return err + } + return nil + } +} + +func init() { + rootCmd.Flags().String("package", "contract", "package name") + rootCmd.Flags().String("name", "", "contract name") + rootCmd.Flags().String("abi", "example.json", "abi json") + rootCmd.Flags().String("outdir", "", "output dir") + rootCmd.Flags().Bool("mock", false, "generate mock") + viper.AutomaticEnv() + viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) +} + func main() { - Execute() + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } } diff --git a/cmd/cligen/cmd.go b/cmd/cligen/cmd.go deleted file mode 100644 index 4b09698..0000000 --- a/cmd/cligen/cmd.go +++ /dev/null @@ -1,73 +0,0 @@ -package main - -import ( - "errors" - "fmt" - "github.com/bluele/hypermint/pkg/account/abi/bind" - clibind "github.com/bluele/hypermint/pkg/account/cli/bind" - "github.com/spf13/cobra" - "github.com/spf13/viper" - "io/ioutil" - "os" - "path" - "strings" -) - -var rootCmd = &cobra.Command{ - Use: "cligen", - Short: "Code generation from ABI", - RunE: func(cmd *cobra.Command, args []string) error { - if err := viper.BindPFlags(cmd.Flags()); err != nil { - return err - } - pkg := viper.GetString("package") - outdir := viper.GetString("outdir") - if len(outdir) == 0 { - outdir = pkg - } - name := viper.GetString("name") - if len(name) == 0 { - return errors.New("name not specified") - } - abi := viper.GetString("abi") - return Generate(outdir, pkg, name, abi) - }, -} - -func Generate(outdir, pkg, name, abiJsonFilename string) error { - if abiJson, err := ioutil.ReadFile(abiJsonFilename); err != nil { - return err - } else if boundSrc, err := bind.Bind(pkg, name, string(abiJson), false); err != nil { - return err - } else if src, err := clibind.Bind(pkg, name, string(abiJson)); err != nil { - return err - } else { - if err := os.MkdirAll(outdir, 0700); err != nil { - return err - } - if err := ioutil.WriteFile(path.Join(outdir, name+".go"), []byte(boundSrc), 0700); err != nil { - return err - } - if err := ioutil.WriteFile(path.Join(outdir, name+"cmd.go"), []byte(src), 0700); err != nil { - return err - } - return nil - } -} - - -func init() { - rootCmd.Flags().String("package", "contract", "package name") - rootCmd.Flags().String("name", "", "contract name") - rootCmd.Flags().String("abi", "example.json", "abi json") - rootCmd.Flags().String("outdir", "", "output dir") - viper.AutomaticEnv() - viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) -} - -func Execute() { - if err := rootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(1) - } -} diff --git a/cmd/cligen/main.go b/cmd/cligen/main.go index 736ef31..b0b41d2 100644 --- a/cmd/cligen/main.go +++ b/cmd/cligen/main.go @@ -1,5 +1,73 @@ package main +import ( + "errors" + "fmt" + "github.com/bluele/hypermint/pkg/account/abi/bind" + clibind "github.com/bluele/hypermint/pkg/account/cli/bind" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "io/ioutil" + "os" + "path" + "strings" +) + +var rootCmd = &cobra.Command{ + Use: "cligen", + Short: "Code generation from ABI", + RunE: func(cmd *cobra.Command, args []string) error { + if err := viper.BindPFlags(cmd.Flags()); err != nil { + return err + } + pkg := viper.GetString("package") + outdir := viper.GetString("outdir") + if len(outdir) == 0 { + outdir = pkg + } + name := viper.GetString("name") + if len(name) == 0 { + return errors.New("name not specified") + } + abi := viper.GetString("abi") + return Generate(outdir, pkg, name, abi) + }, +} + +func Generate(outdir, pkg, name, abiJsonFilename string) error { + if abiJson, err := ioutil.ReadFile(abiJsonFilename); err != nil { + return err + } else if boundSrc, err := bind.Bind(pkg, name, string(abiJson), false); err != nil { + return err + } else if src, err := clibind.Bind(pkg, name, string(abiJson)); err != nil { + return err + } else { + if err := os.MkdirAll(outdir, 0700); err != nil { + return err + } + if err := ioutil.WriteFile(path.Join(outdir, name+".go"), []byte(boundSrc), 0700); err != nil { + return err + } + if err := ioutil.WriteFile(path.Join(outdir, name+"cmd.go"), []byte(src), 0700); err != nil { + return err + } + return nil + } +} + + +func init() { + rootCmd.Flags().String("package", "contract", "package name") + rootCmd.Flags().String("name", "", "contract name") + rootCmd.Flags().String("abi", "example.json", "abi json") + rootCmd.Flags().String("outdir", "", "output dir") + viper.AutomaticEnv() + viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) +} + func main() { - Execute() + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } } From 7bac69b4cf7c7256d19f58bc5a8beefc9f65eac1 Mon Sep 17 00:00:00 2001 From: Kiyoshi Nakao Date: Mon, 21 Oct 2019 17:09:59 +0900 Subject: [PATCH 13/24] remove unused code --- cmd/abigen/.gitignore | 1 - cmd/abigen/Makefile | 11 ----------- cmd/abigen/README.md | 8 +------- cmd/cligen/Makefile | 8 ++------ 4 files changed, 3 insertions(+), 25 deletions(-) delete mode 100644 cmd/abigen/.gitignore delete mode 100644 cmd/abigen/Makefile diff --git a/cmd/abigen/.gitignore b/cmd/abigen/.gitignore deleted file mode 100644 index 7f0286d..0000000 --- a/cmd/abigen/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/abigen diff --git a/cmd/abigen/Makefile b/cmd/abigen/Makefile deleted file mode 100644 index f231bd4..0000000 --- a/cmd/abigen/Makefile +++ /dev/null @@ -1,11 +0,0 @@ - -.PHONY: test -test: - go build - ./abigen --outdir example --name token --package main --abi example/token.json --mock - (cd example && go test) - -.PHONY: gen-example -gen-example: - mkdir -p example - (cd ../../hmcdk/genabi && cargo run ../../example/token/src/lib.rs) > example/token.json diff --git a/cmd/abigen/README.md b/cmd/abigen/README.md index 6ff3443..a6a2bc3 100644 --- a/cmd/abigen/README.md +++ b/cmd/abigen/README.md @@ -1,9 +1,3 @@ # abigen -A go-ethereum like contract call code generator from ABI json - -## Test - -``` -$ make example -``` +A go-ethereum like contract call code generator diff --git a/cmd/cligen/Makefile b/cmd/cligen/Makefile index ef174a6..688d3ad 100644 --- a/cmd/cligen/Makefile +++ b/cmd/cligen/Makefile @@ -1,11 +1,7 @@ .PHONY: test -test: gen-example +test: + (cd ../../hmcdk/genabi && cargo run ../../example/token/src/lib.rs) > example/token.json go build ./cligen --outdir example --name token --package main --abi example/token.json (cd example && go build) - -.PHONY: gen-example -gen-example: - mkdir -p example - (cd ../../hmcdk/genabi && cargo run ../../example/token/src/lib.rs) > example/token.json From f1b196714a7310595a468a26127a3fcee502a85f Mon Sep 17 00:00:00 2001 From: Kiyoshi Nakao Date: Mon, 21 Oct 2019 18:25:49 +0900 Subject: [PATCH 14/24] add cligen test --- Makefile | 3 + go.mod | 6 +- go.sum | 86 ++++++++++++++++++ pkg/account/cli/bind/template.go | 20 ++--- tests/.gitignore | 3 +- tests/Makefile | 7 ++ tests/cligen/cligen_test.go | 106 +++++++++++++++++++++++ tests/contracts/contract_test/Cargo.lock | 44 +++++++++- tests/contracts/contract_test/src/lib.rs | 14 +-- tests/e2e/common/node.go | 4 + 10 files changed, 270 insertions(+), 23 deletions(-) create mode 100644 tests/cligen/cligen_test.go diff --git a/Makefile b/Makefile index b204f38..87456b3 100644 --- a/Makefile +++ b/Makefile @@ -76,6 +76,9 @@ integration-test: e2e-test: $(MAKE) -C ./tests e2e-test +cligen-test: + $(MAKE) -C ./tests cligen-test + build-image: docker build . -t bluele/hypermint:${VERSION} diff --git a/go.mod b/go.mod index 86eaf97..766e899 100644 --- a/go.mod +++ b/go.mod @@ -28,9 +28,9 @@ require ( github.com/perlin-network/life v0.0.0-20181106205055-98065d82a6ee github.com/pkg/errors v0.8.1 github.com/rjeczalik/notify v0.9.2 // indirect - github.com/spf13/cobra v0.0.1 - github.com/spf13/pflag v1.0.3 - github.com/spf13/viper v1.0.0 + github.com/spf13/cobra v0.0.5 + github.com/spf13/pflag v1.0.5 + github.com/spf13/viper v1.4.0 github.com/stretchr/testify v1.3.0 github.com/tendermint/go-amino v0.14.1 github.com/tendermint/iavl v0.12.4 diff --git a/go.sum b/go.sum index 04ec162..5c57de9 100644 --- a/go.sum +++ b/go.sum @@ -1,16 +1,22 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/allegro/bigcache v1.2.0 h1:qDaE0QoF29wKBb3+pXFrJFy1ihe5OT9OiXhg1t85SxM= github.com/allegro/bigcache v1.2.0/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/aristanetworks/goarista v0.0.0-20180627184309-2c5933638c5e/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= github.com/aristanetworks/goarista v0.0.0-20181002214814-33151c4543a7 h1:6TQIK3K21/HnYLp+TAI6fjQ1YeH+KgLZbrFJwUjVrnQ= github.com/aristanetworks/goarista v0.0.0-20181002214814-33151c4543a7/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/btcsuite/btcd v0.0.0-20180531025944-86fed781132a/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= @@ -27,13 +33,23 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ= github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/etcd-io/bbolt v1.3.2/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/etcd-io/bbolt v1.3.3 h1:gSJmxrs37LgTqR/oyJBWok6k6SvXEUerFTbltIhXkBM= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= @@ -45,26 +61,35 @@ github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8 github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-kit/kit v0.6.0 h1:wTifptAGIyIuir4bRyN4h7+kAa2a4eepLYVmRe5qqQ8= github.com/go-kit/kit v0.6.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0 h1:8HUsc87TaSWLKwrnumgC8/YconD2fJQsRJAsWaPg2ic= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-stack/stack v1.7.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -72,6 +97,11 @@ github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ= github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= @@ -85,10 +115,13 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= @@ -107,8 +140,11 @@ github.com/mattn/go-shellwords v1.0.5/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vq github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miguelmota/go-ethereum-hdwallet v0.0.0-20190720004541-5f6b3168e4a0/go.mod h1:VVt+rn/itmf+9eZq9CAabVlsfsHveUNUQ0bRv3ChqxY= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -134,33 +170,56 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1 h1:K47Rk0v/fkEfwfQet2KWhscE0cJzjgCCDBG2KHZoVno= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39 h1:Cto4X6SVMWRPBkJ/3YHn1iDGDGc/Z+sW+AEMKHMVvN4= github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d h1:GoAlyOgbOEIFdaDqxJVlbOQ1DtGmZWs/Qau0hIlk+WQ= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165 h1:nkcn14uNmFEuGCb2mBZbBb24RdNRL08b/wb+xBOYpuk= github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI= github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa/go.mod h1:oJyF+mSPHbB5mVY2iO9KV3pTt/QbIkGaO8gQ2WrDbP4= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.1 h1:zZh3X5aZbdnoj+4XkaBxKfhO4ot82icYdhhREIAXIj8= github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.0.0 h1:RUA/ghS2i64rlnn4ydTfblY8Og8QzcPtCcHvgMn+w/I= github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -176,13 +235,24 @@ github.com/tendermint/tendermint v0.32.3 h1:GEnWpGQ795h5oTFNbfBLsY0LW/CW2j6p6Hti github.com/tendermint/tendermint v0.32.3/go.mod h1:ZK2c29jl1QRYznIRyRWRDsmm1yvtPzBRT00x4t1JToY= github.com/tendermint/tm-db v0.1.1 h1:G3Xezy3sOk9+ekhjZ/kjArYIs1SmwV+1OUgNkj7RgV0= github.com/tendermint/tm-db v0.1.1/go.mod h1:0cPKWu2Mou3IlxecH+MEUSYc1Ch537alLe6CpFrKzgw= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tyler-smith/go-bip39 v0.0.0-20180618194314-52158e4697b8/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/tyler-smith/go-bip39 v0.3.6 h1:HHfkwlRk4+99y7QbMS1I/tuiSE5rctNLqpeH6uUQROU= github.com/tyler-smith/go-bip39 v0.3.6/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -196,21 +266,29 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190628185345-da137c7871d7 h1:rTIdg5QFRR7XCaK4LCjBiPbx8j4DQRpdYMnGn/bJUEU= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -220,6 +298,7 @@ golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -236,18 +315,25 @@ google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64 h1:iKtrH9Y8mcbADOP google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/grpc v1.13.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.22.0 h1:J0UbZOIrCAl+fpTOf8YLs4dJo8L/owV4LYVtAXQoPkw= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.22.1 h1:/7cs52RnTJmD43s3uxzlq2U7nqVTd/37viQwMrMNlOM= google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/karalabe/cookiejar.v2 v2.0.0-20150724131613-8dcd6a7f4951/go.mod h1:owOxCRGGeAx1uugABik6K9oeNu1cgxP/R9ItzLDxNWA= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/pkg/account/cli/bind/template.go b/pkg/account/cli/bind/template.go index 9fbe3fe..d11e59f 100644 --- a/pkg/account/cli/bind/template.go +++ b/pkg/account/cli/bind/template.go @@ -52,6 +52,7 @@ var ( cmd.PersistentFlags().String("caller", callerAddress, "caller") cmd.PersistentFlags().String("contract", contractAddress, "contract") cmd.PersistentFlags().String("endpoint", "{{$endpoint}}", "endpoint") + cmd.PersistentFlags().String("ksdir", "keystore", "keystore directory") {{range .Functions -}} cmd.AddCommand({{$contract.Name}}{{.Name}}Cmd) {{end}} @@ -77,6 +78,9 @@ var ( Use: "{{.Use}}", Short: "{{.Short}}", RunE: func(cmd *cobra.Command, args []string) error { + if cmd.OutOrStderr() == os.Stderr { + cmd.SetOut(os.Stdout) + } if err := viper.BindPFlags(cmd.Flags()); err != nil { return err } @@ -106,7 +110,7 @@ var ( fmt.Fprintf(os.Stderr, "passphrase=%v\n", viper.GetString("passphrase")) } - ks := clibind.NewKeyStore("keystore") + ks := clibind.NewKeyStore(viper.GetString("ksdir")) opts, c, err := {{$contract.Name}}ContractFromFlags(ks) if err != nil { return err @@ -129,13 +133,9 @@ var ( } {{range $i, $o := .Outputs}} {{if eq .Type.Name "address"}} - if _, err := fmt.Fprintln(os.Stdout, v{{$i}}.Hex()); err != nil { - return err - } + cmd.Println(v{{$i}}.Hex()) {{else}} - if _, err := fmt.Fprintln(os.Stdout, v{{$i}}); err != nil { - return err - } + cmd.Println(v{{$i}}) {{end}} {{end}} return nil @@ -169,9 +169,9 @@ var ( fmt.Fprintf(os.Stderr, "%v\n", err.Error()) } } else { - if verbose { - fmt.Fprintf(os.Stderr, "found\n") - } + if verbose { + fmt.Fprintf(os.Stderr, "found\n") + } json.NewEncoder(os.Stdout).Encode(&_{{.Name}}) } {{end}} diff --git a/tests/.gitignore b/tests/.gitignore index d163863..93d98e8 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1 +1,2 @@ -build/ \ No newline at end of file +build/ +cligen/contract_test* diff --git a/tests/Makefile b/tests/Makefile index 8c08382..21a963f 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -2,6 +2,7 @@ GO_BIN?=go GO_TEST_FLAGS?=-v -count=1 GO_TEST_CMD=$(GO_BIN) test $(GO_TEST_FLAGS) VERSION ?= v0.2.0 +TOP_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))/.. build-image: docker build . -t hypermint/go-rust:$(VERSION) @@ -19,3 +20,9 @@ integration-test: contract_test.wasm e2e-test: contract_test.wasm external_contract_test.wasm @$(GO_TEST_CMD) ./e2e/... + +cligen-test: contract_test.wasm + make -C .. abigen cligen + (cd $(TOP_DIR)/hmcdk/genabi && cargo run $(TOP_DIR)/tests/contracts/contract_test/src/lib.rs) > cligen/contract_test.json + $(TOP_DIR)/build/cligen --outdir cligen --name contract_test --package cligen --abi cligen/contract_test.json + @$(GO_TEST_CMD) ./cligen/... diff --git a/tests/cligen/cligen_test.go b/tests/cligen/cligen_test.go new file mode 100644 index 0000000..635f5a4 --- /dev/null +++ b/tests/cligen/cligen_test.go @@ -0,0 +1,106 @@ +package cligen + +import ( + "bytes" + "context" + "fmt" + ecommon "github.com/bluele/hypermint/tests/e2e/common" + "github.com/ethereum/go-ethereum/common" + "github.com/spf13/cobra" + "github.com/stretchr/testify/suite" + "path/filepath" + "regexp" + "testing" + "time" + + cmn "github.com/tendermint/tendermint/libs/common" +) + +const ( + testContractPath = "../build/contract_test.wasm" +) + +func TestCligenTestSuite(t *testing.T) { + suite.Run(t, new(CligenTestSuite)) +} + +type CligenTestSuite struct { + ecommon.NodeTestSuite +} + +func (ts *CligenTestSuite) SetupTest() { + pjRoot, err := filepath.Abs(filepath.Join("..", "..")) + if err != nil { + ts.FailNow("failed to call Abs()", err.Error()) + } + // TODO these values should be configurable? + ts.Setup( + filepath.Join(pjRoot, "build"), + filepath.Join(filepath.Join(pjRoot, ".hm"), cmn.RandStr(8)), + ) +} + +func (ts *CligenTestSuite) TearDownTest() { + ts.TearDown() +} + +func (ts *CligenTestSuite) TestCLI() { + ctx := context.Background() + c, err := ts.DeployContract(ctx, ts.Account(1), testContractPath) + if !ts.NoError(err) { + return + } + + caller := ts.Account(0) + + var rootCmd = &cobra.Command{ + Use: "test", + Short: "Test CLI", + } + + for _, tc := range []struct{ + suc bool + args []string + outregex string + }{ + { true, []string{"help"}, `.*$`}, + { true, []string{"test-get-sender"}, caller.Hex()+`\n$`}, + { true, []string{"test-get-contract-address"}, c.Hex()+`\n$`}, + } { + args := append([]string{"contract_test", "--passphrase", "password", "--ksdir", ts.GetCLIHomeDir()}, tc.args...) + buf := new(bytes.Buffer) + rootCmd.SetOut(buf) + rootCmd.SetArgs(args) + rootCmd.AddCommand(ContractTestCmd(c.Hex(), caller.Hex())) + if err := rootCmd.Execute(); tc.suc != (err == nil) { + if err != nil { + ts.T().Error(err) + } else { + ts.T().Fail() + } + } + output := buf.String() + r := regexp.MustCompile(tc.outregex) + if !r.MatchString(output) { + ts.T().Error(output, "does not match with the regexp", "'"+tc.outregex+"'", args) + } + } +} + +func (ts *CligenTestSuite) DeployContract(ctx context.Context, from common.Address, path string) (common.Address, error) { + cmd := fmt.Sprintf("contract deploy --address=%v --path=%v --gas=1 --password=password", from.Hex(), path) + address, err := ts.sendTxCMD(ctx, cmd) + if err != nil { + return common.Address{}, err + } + return common.HexToAddress(string(address)), nil +} + +func (ts *CligenTestSuite) sendTxCMD(ctx context.Context, cmd string) ([]byte, error) { + if out, e, err := ts.ExecCLICommand(ctx, cmd); err != nil { + return nil, fmt.Errorf("%v:%v:%v", string(out), string(e), err) + } else { + time.Sleep(2 * ts.TimeoutCommit) + return out, nil + } +} diff --git a/tests/contracts/contract_test/Cargo.lock b/tests/contracts/contract_test/Cargo.lock index c069112..3b5f70e 100644 --- a/tests/contracts/contract_test/Cargo.lock +++ b/tests/contracts/contract_test/Cargo.lock @@ -1,5 +1,9 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "abi" +version = "0.1.0" + [[package]] name = "backtrace" version = "0.3.37" @@ -69,8 +73,9 @@ dependencies = [ name = "hmcdk_codegen" version = "0.1.0" dependencies = [ - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", + "abi 0.1.0", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -86,6 +91,14 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro2" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quote" version = "0.6.13" @@ -94,6 +107,14 @@ dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quote" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc-demangle" version = "0.1.16" @@ -109,6 +130,16 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "synstructure" version = "0.10.2" @@ -125,6 +156,11 @@ name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [metadata] "checksum backtrace 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)" = "5180c5a20655b14a819b652fd2378fa5f1697b6c9ddad3e695c2f9cedf6df4e2" "checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" @@ -134,8 +170,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" diff --git a/tests/contracts/contract_test/src/lib.rs b/tests/contracts/contract_test/src/lib.rs index 60ed7be..8a565d2 100644 --- a/tests/contracts/contract_test/src/lib.rs +++ b/tests/contracts/contract_test/src/lib.rs @@ -16,24 +16,24 @@ fn call_check_signature() -> Result { } } -#[contract] +#[contract(readonly)] pub fn test_get_sender() -> R
{ Ok(Some(get_sender()?)) } -#[contract] +#[contract(readonly)] pub fn test_get_contract_address() -> R
{ Ok(Some(get_contract_address()?)) } -#[contract] +#[contract(readonly)] pub fn test_get_arguments() -> R> { let argIdx: i32 = get_arg(0)?; let arg: Vec = get_arg(argIdx as usize)?; Ok(Some(arg)) } -#[contract] +#[contract(readonly)] pub fn check_signature() -> R { Ok(Some(call_check_signature()?)) } @@ -59,7 +59,7 @@ pub fn test_write_state() -> R { Ok(None) } -#[contract] +#[contract(readonly)] pub fn test_read_state() -> R> { let key: Vec = get_arg(0)?; let value: Vec = match read_state(&key) { @@ -113,13 +113,13 @@ pub fn test_write_to_multiple_key() -> R { Ok(None) } -#[contract] +#[contract(readonly)] pub fn test_keccak256() -> R> { let msg: Vec = get_arg(0)?; Ok(Some(keccak256(&msg)?.to_vec())) } -#[contract] +#[contract(readonly)] pub fn test_sha256() -> R> { let msg: Vec = get_arg(0)?; Ok(Some(sha256(&msg)?.to_vec())) diff --git a/tests/e2e/common/node.go b/tests/e2e/common/node.go index df0a8b1..01a998f 100644 --- a/tests/e2e/common/node.go +++ b/tests/e2e/common/node.go @@ -163,6 +163,10 @@ func (ts *NodeTestSuite) RPCClient() rpclient.Client { return rpclient.NewHTTP(c.RPC.ListenAddress, "/websocket") } +func (ts *NodeTestSuite) GetCLIHomeDir() string { + return ts.hmcliHomeDir +} + type Env interface { String() string } From d3c359e115bca131bf8584510f9187e09559eea6 Mon Sep 17 00:00:00 2001 From: Kiyoshi Nakao Date: Mon, 21 Oct 2019 19:50:18 +0900 Subject: [PATCH 15/24] add abi crate --- hmcdk/abi/Cargo.toml | 9 ++++ hmcdk/abi/src/lib.rs | 2 + hmcdk/abi/src/types.rs | 59 ++++++++++++++++++++++++ tests/contracts/contract_test/Cargo.lock | 5 -- 4 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 hmcdk/abi/Cargo.toml create mode 100644 hmcdk/abi/src/lib.rs create mode 100644 hmcdk/abi/src/types.rs diff --git a/hmcdk/abi/Cargo.toml b/hmcdk/abi/Cargo.toml new file mode 100644 index 0000000..9718ea9 --- /dev/null +++ b/hmcdk/abi/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "abi" +version = "0.1.0" +authors = ["Kiyoshi Nakao "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/hmcdk/abi/src/lib.rs b/hmcdk/abi/src/lib.rs new file mode 100644 index 0000000..a7cbed3 --- /dev/null +++ b/hmcdk/abi/src/lib.rs @@ -0,0 +1,2 @@ + +pub mod types; diff --git a/hmcdk/abi/src/types.rs b/hmcdk/abi/src/types.rs new file mode 100644 index 0000000..2065b8e --- /dev/null +++ b/hmcdk/abi/src/types.rs @@ -0,0 +1,59 @@ +pub enum AbiInteger { + I8, + I16, + I32, + I64, + U8, + U16, + U32, + U64, +} + +pub enum AbiPrimitive { + Integer(AbiInteger), + Bytes, + Address, + Hash, +} + +pub fn get_primitive_name(prim: AbiPrimitive) -> String { + use AbiPrimitive::*; + use AbiInteger::*; + + match prim { + Integer(x) => match x { + I8 => "i8", + I16 => "i16", + I32 => "i32", + I64 => "i64", + U8 => "u8", + U16 => "u16", + U32 => "u32", + U64 => "u64", + }, + Bytes => "bytes", + Address => "address", + Hash => "hash", + }.to_string() +} + +pub fn to_abi_primitive(rust_type: &String) -> Option { + use AbiPrimitive::*; + use AbiInteger::*; + + let t = rust_type.as_str(); + match t { + "i8" => Some(Integer(I8)), + "i16" => Some(Integer(I16)), + "i32" => Some(Integer(I32)), + "i64" => Some(Integer(I64)), + "u8" => Some(Integer(U8)), + "u16" => Some(Integer(U16)), + "u32" => Some(Integer(U32)), + "u64" => Some(Integer(U64)), + "Address" => Some(Address), + "Hash" => Some(Hash), + "Vec" => Some(Bytes), + _ => None, + } +} diff --git a/tests/contracts/contract_test/Cargo.lock b/tests/contracts/contract_test/Cargo.lock index 3b5f70e..9124777 100644 --- a/tests/contracts/contract_test/Cargo.lock +++ b/tests/contracts/contract_test/Cargo.lock @@ -1,9 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "abi" -version = "0.1.0" - [[package]] name = "backtrace" version = "0.3.37" @@ -73,7 +69,6 @@ dependencies = [ name = "hmcdk_codegen" version = "0.1.0" dependencies = [ - "abi 0.1.0", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] From 7c46360a0ee549b310efe3410ecce1f1c9fda176 Mon Sep 17 00:00:00 2001 From: Kiyoshi Nakao Date: Mon, 21 Oct 2019 19:54:47 +0900 Subject: [PATCH 16/24] run cligen-test job on CI --- .circleci/config.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3068f3d..4875668 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -81,6 +81,21 @@ jobs: command: | make e2e-test + cligen-test: + working_directory: /go/src/github.com/bluele/hypermint + docker: + - image: hypermint/go-rust:v0.2.0 + environment: + GO111MODULE: "on" + steps: + - checkout + - attach_workspace: + at: / + - run: + name: "cligen-test" + command: | + make cligen-test + pre-release: <<: *release_config steps: @@ -133,6 +148,12 @@ workflows: only: /.*/ requires: - build + - cligen-test: + filters: + tags: + only: /.*/ + requires: + - build pre-release: jobs: - pre-release: From b84218f342e05ef9422639203ba32bf28db47fc8 Mon Sep 17 00:00:00 2001 From: Kiyoshi Nakao Date: Mon, 21 Oct 2019 21:45:49 +0900 Subject: [PATCH 17/24] fix subcommand name of generated command --- pkg/account/cli/bind/bind.go | 2 +- tests/cligen/cligen_test.go | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkg/account/cli/bind/bind.go b/pkg/account/cli/bind/bind.go index ed1ac9a..ab0c7e8 100644 --- a/pkg/account/cli/bind/bind.go +++ b/pkg/account/cli/bind/bind.go @@ -63,7 +63,7 @@ func Bind(packageName string, name, jsonABI string) (string, error) { c := tmplContract{ Type: strcase.ToCamel(name), Name: name, - Use: name, + Use: strcase.ToDelimited(name, '-'), Short: name, Functions: functions, Events: abi.Events, diff --git a/tests/cligen/cligen_test.go b/tests/cligen/cligen_test.go index 635f5a4..0a4c4e3 100644 --- a/tests/cligen/cligen_test.go +++ b/tests/cligen/cligen_test.go @@ -53,11 +53,6 @@ func (ts *CligenTestSuite) TestCLI() { caller := ts.Account(0) - var rootCmd = &cobra.Command{ - Use: "test", - Short: "Test CLI", - } - for _, tc := range []struct{ suc bool args []string @@ -67,7 +62,12 @@ func (ts *CligenTestSuite) TestCLI() { { true, []string{"test-get-sender"}, caller.Hex()+`\n$`}, { true, []string{"test-get-contract-address"}, c.Hex()+`\n$`}, } { - args := append([]string{"contract_test", "--passphrase", "password", "--ksdir", ts.GetCLIHomeDir()}, tc.args...) + var rootCmd = &cobra.Command{ + Use: "test", + Short: "Test CLI", + } + + args := append([]string{"contract-test", "--passphrase", "password", "--ksdir", ts.GetCLIHomeDir()}, tc.args...) buf := new(bytes.Buffer) rootCmd.SetOut(buf) rootCmd.SetArgs(args) From c5e497f37875081d25358ef02e9835420dbe3cf1 Mon Sep 17 00:00:00 2001 From: Kiyoshi Nakao Date: Mon, 21 Oct 2019 22:28:17 +0900 Subject: [PATCH 18/24] fix contract macro --- hmcdk/codegen/src/lib.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/hmcdk/codegen/src/lib.rs b/hmcdk/codegen/src/lib.rs index 6486e96..dd7820d 100644 --- a/hmcdk/codegen/src/lib.rs +++ b/hmcdk/codegen/src/lib.rs @@ -11,11 +11,9 @@ fn get_assignment_from_name_and_type( index: usize, ) -> Result { match ty { - Type::Path(type_path) => { - let pair = type_path.path.segments.last().ok_or("internal error")?; - let ident = &pair.ident; + Type::Path(_type_path) => { let a = parse_quote! { - let #name: #ident = get_arg(#index).unwrap(); + let #name: #ty = get_arg(#index).unwrap(); }; Ok(a) } From e2f2d528ffd5aa8f2a7e92c6cd967958c0949ea4 Mon Sep 17 00:00:00 2001 From: Kiyoshi Nakao Date: Mon, 21 Oct 2019 22:29:20 +0900 Subject: [PATCH 19/24] give parameters with function arguments --- tests/contracts/contract_test/src/lib.rs | 59 ++++++------------------ 1 file changed, 15 insertions(+), 44 deletions(-) diff --git a/tests/contracts/contract_test/src/lib.rs b/tests/contracts/contract_test/src/lib.rs index 8a565d2..f6941c9 100644 --- a/tests/contracts/contract_test/src/lib.rs +++ b/tests/contracts/contract_test/src/lib.rs @@ -27,14 +27,13 @@ pub fn test_get_contract_address() -> R
{ } #[contract(readonly)] -pub fn test_get_arguments() -> R> { - let argIdx: i32 = get_arg(0)?; - let arg: Vec = get_arg(argIdx as usize)?; +pub fn test_get_arguments(arg_idx: i32) -> R> { + let arg: Vec = get_arg(arg_idx as usize)?; Ok(Some(arg)) } #[contract(readonly)] -pub fn check_signature() -> R { +pub fn check_signature(msg_hash: Vec, sig: Vec) -> R { Ok(Some(call_check_signature()?)) } @@ -52,16 +51,13 @@ pub fn test_read_uncommitted_state() -> R { } #[contract] -pub fn test_write_state() -> R { - let key: Vec = get_arg(0)?; - let value: Vec = get_arg(1)?; +pub fn test_write_state(key: Vec, value: Vec) -> R { write_state(&key, &value); Ok(None) } #[contract(readonly)] -pub fn test_read_state() -> R> { - let key: Vec = get_arg(0)?; +pub fn test_read_state(key: Vec) -> R> { let value: Vec = match read_state(&key) { Ok(v) => v, Err(_) => vec![], @@ -70,10 +66,7 @@ pub fn test_read_state() -> R> { } #[contract] -pub fn test_read_write_state() -> R { - let key: Vec = get_arg(0)?; - let value: Vec = get_arg(1)?; - +pub fn test_read_write_state(key: Vec, value: Vec) -> R { // read a value, but nop read_state::>(&key); @@ -82,11 +75,7 @@ pub fn test_read_write_state() -> R { } #[contract] -pub fn test_write_to_same_key() -> R { - let key: Vec = get_arg(0)?; - let value1: Vec = get_arg(1)?; - let value2: Vec = get_arg(2)?; - +pub fn test_write_to_same_key(key: Vec, value1: Vec, value2: Vec) -> R { // read a value, but nop read_state::>(&key); @@ -97,12 +86,7 @@ pub fn test_write_to_same_key() -> R { } #[contract] -pub fn test_write_to_multiple_key() -> R { - let key1: Vec = get_arg(0)?; - let value1: Vec = get_arg(1)?; - let key2: Vec = get_arg(2)?; - let value2: Vec = get_arg(3)?; - +pub fn test_write_to_multiple_key(key1: Vec, value1: Vec, key2: Vec, value2: Vec) -> R { // read a value, but nop read_state::>(&key1); read_state::>(&key2); @@ -114,21 +98,17 @@ pub fn test_write_to_multiple_key() -> R { } #[contract(readonly)] -pub fn test_keccak256() -> R> { - let msg: Vec = get_arg(0)?; +pub fn test_keccak256(msg: Vec) -> R> { Ok(Some(keccak256(&msg)?.to_vec())) } #[contract(readonly)] -pub fn test_sha256() -> R> { - let msg: Vec = get_arg(0)?; +pub fn test_sha256(msg: Vec) -> R> { Ok(Some(sha256(&msg)?.to_vec())) } #[contract] -pub fn test_emit_event() -> R> { - let msg0: Vec = get_arg(0)?; - let msg1: Vec = get_arg(1)?; +pub fn test_emit_event(msg0: Vec, msg1: Vec) -> R> { let name0 = "test-event-name-0"; let name1 = "test-event-name-1"; @@ -138,11 +118,7 @@ pub fn test_emit_event() -> R> { } #[contract] -pub fn test_external_emit_event() -> R> { - let org_msg: Vec = get_arg(0)?; - let addr: Address = get_arg(1)?; - let ext_msg: Vec = get_arg(2)?; - +pub fn test_external_emit_event(org_msg: Vec, addr: Address, ext_msg: Vec) -> R> { let _: Vec = call_contract(&addr, "test_emit_event".as_bytes(), vec![&ext_msg])?; let name = "test-org-event-name"; emit_event(name, &org_msg)?; @@ -150,22 +126,17 @@ pub fn test_external_emit_event() -> R> { } #[contract] -pub fn test_call_external_contract() -> R> { - let addr: Address = get_arg(0)?; - let x: Vec = get_arg(1)?; - let y: Vec = get_arg(2)?; +pub fn test_call_external_contract(addr: Address, x: Vec, y: Vec) -> R> { Ok(Some(call_contract(&addr, "test_plus".as_bytes(), vec![&x, &y])?)) } #[contract] -pub fn test_call_who_am_i_on_external_contract() -> R> { - let addr: Address = get_arg(0)?; +pub fn test_call_who_am_i_on_external_contract(addr: Address) -> R> { Ok(Some(call_contract(&addr, "who_am_i".as_bytes(), vec![])?)) } #[contract] -pub fn test_call_get_contract_address_on_external_contract() -> R> { - let addr: Address = get_arg(0)?; +pub fn test_call_get_contract_address_on_external_contract(addr: Address) -> R> { Ok(Some(call_contract(&addr, "get_contract_address".as_bytes(), vec![])?)) } From f06939597dedb6e432348fd0ee20f7c5277cd2d1 Mon Sep 17 00:00:00 2001 From: Kiyoshi Nakao Date: Tue, 22 Oct 2019 00:07:10 +0900 Subject: [PATCH 20/24] support bytes type --- pkg/account/abi/bind/primitives.go | 6 ++++++ pkg/account/abi/bind/template.go | 5 +++-- pkg/account/abi/type.go | 2 ++ pkg/account/cli/bind/template.go | 9 +++++++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/pkg/account/abi/bind/primitives.go b/pkg/account/abi/bind/primitives.go index e23c521..3865cd7 100644 --- a/pkg/account/abi/bind/primitives.go +++ b/pkg/account/abi/bind/primitives.go @@ -82,6 +82,12 @@ func (s String) Bytes() []byte { return []byte(s) } +type Bytes []byte + +func (s Bytes) Bytes() []byte { + return s +} + type Address common.Address func (a Address) Bytes() []byte { diff --git a/pkg/account/abi/bind/template.go b/pkg/account/abi/bind/template.go index e84a9be..649dfd1 100644 --- a/pkg/account/abi/bind/template.go +++ b/pkg/account/abi/bind/template.go @@ -203,11 +203,12 @@ var ( buf := bytes.NewBuffer(result.Data) {{end}} {{range $i, $v := .Outputs -}} + var v{{ $i }} {{.Type.TypeName}} {{if eq .Type.TypeName "string"}} - var v{{ $i }} {{.Type.TypeName}} v{{ $i }} = buf.String() + {{else if eq .Type.TypeName "[]byte"}} + v{{ $i }} = buf.Bytes() {{else}} - var v{{ $i }} {{.Type.TypeName}} binary.Read(buf, binary.BigEndian, &v{{ $i }}) {{end}} {{end -}} diff --git a/pkg/account/abi/type.go b/pkg/account/abi/type.go index 73975c4..7377a87 100644 --- a/pkg/account/abi/type.go +++ b/pkg/account/abi/type.go @@ -125,6 +125,8 @@ func (t Type) BoundType() string { op = "bind.Bool" case StringTy: op = "bind.String" + case BytesTy: + op = "bind.Bytes" case AddressTy: op = "bind.Address" case HashTy: diff --git a/pkg/account/cli/bind/template.go b/pkg/account/cli/bind/template.go index d11e59f..9374c89 100644 --- a/pkg/account/cli/bind/template.go +++ b/pkg/account/cli/bind/template.go @@ -14,6 +14,7 @@ import ( "strings" "encoding/binary" "bytes" + "encoding/base64" "encoding/json" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -38,6 +39,7 @@ var ( _ = bytes.NewBuffer _ = binary.Read _ = json.NewEncoder + _ = base64.StdPadding ) {{$endpoint := .Endpoint}} @@ -99,6 +101,11 @@ var ( arg{{.Name}} := common.HexToHash(viper.GetString("{{.Name}}")) {{else if eq .Type.Name "bool"}} arg{{.Name}} := viper.GetBool("{{.Name}}") + {{else if eq .Type.Name "bytes"}} + arg{{.Name}}, err := base64.StdEncoding.DecodeString(viper.GetString("{{.Name}}")) + if err != nil { + return errors.New("invalid bytes") + } {{else}} arg{{.Name}} := {{.Type.TypeName}}(viper.GetInt64("{{.Name}}")) {{end}} @@ -134,6 +141,8 @@ var ( {{range $i, $o := .Outputs}} {{if eq .Type.Name "address"}} cmd.Println(v{{$i}}.Hex()) + {{else if eq .Type.Name "bytes"}} + cmd.Println(base64.StdEncoding.EncodeToString(v{{$i}})) {{else}} cmd.Println(v{{$i}}) {{end}} From bdbde6668d2ccaf8e8e076c5d3de70fdf97df7f1 Mon Sep 17 00:00:00 2001 From: Kiyoshi Nakao Date: Tue, 22 Oct 2019 00:34:11 +0900 Subject: [PATCH 21/24] add test-write-state command test --- tests/cligen/cligen_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/cligen/cligen_test.go b/tests/cligen/cligen_test.go index 0a4c4e3..caaa554 100644 --- a/tests/cligen/cligen_test.go +++ b/tests/cligen/cligen_test.go @@ -51,7 +51,7 @@ func (ts *CligenTestSuite) TestCLI() { return } - caller := ts.Account(0) + caller := ts.Account(1) for _, tc := range []struct{ suc bool @@ -61,6 +61,8 @@ func (ts *CligenTestSuite) TestCLI() { { true, []string{"help"}, `.*$`}, { true, []string{"test-get-sender"}, caller.Hex()+`\n$`}, { true, []string{"test-get-contract-address"}, c.Hex()+`\n$`}, + { true, []string{"test-write-state", "--key", "a2V5", "--value", "dmFsdWU="}, `$`}, + { true, []string{"test-read-state", "--key", "a2V5"}, `dmFsdWU=\n$`}, } { var rootCmd = &cobra.Command{ Use: "test", From 585c5a08187f0f9b7675b28bad20830df74881fe Mon Sep 17 00:00:00 2001 From: Kiyoshi Nakao Date: Tue, 22 Oct 2019 00:51:09 +0900 Subject: [PATCH 22/24] fix cligen command --- cmd/abigen/README.md | 3 --- cmd/abigen/main.go | 6 +++--- cmd/cligen/.gitignore | 4 ---- cmd/cligen/Makefile | 7 ------- cmd/cligen/example/main.go | 32 -------------------------------- cmd/cligen/main.go | 8 ++++---- 6 files changed, 7 insertions(+), 53 deletions(-) delete mode 100644 cmd/abigen/README.md delete mode 100644 cmd/cligen/.gitignore delete mode 100644 cmd/cligen/Makefile delete mode 100644 cmd/cligen/example/main.go diff --git a/cmd/abigen/README.md b/cmd/abigen/README.md deleted file mode 100644 index a6a2bc3..0000000 --- a/cmd/abigen/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# abigen - -A go-ethereum like contract call code generator diff --git a/cmd/abigen/main.go b/cmd/abigen/main.go index d6bc2c0..556cc8b 100644 --- a/cmd/abigen/main.go +++ b/cmd/abigen/main.go @@ -40,10 +40,10 @@ func Generate(outdir, pkg, name, abiJsonFilename string, mock bool) error { } else if src, err := bind.Bind(pkg, name, string(abiJson), mock); err != nil { return err } else { - if err := os.MkdirAll(pkg, 0700); err != nil { + if err := os.MkdirAll(pkg, 0755); err != nil { return err } - if err := ioutil.WriteFile(path.Join(outdir, name+".go"), []byte(src), 0700); err != nil { + if err := ioutil.WriteFile(path.Join(outdir, name+".go"), []byte(src), 0644); err != nil { return err } return nil @@ -53,7 +53,7 @@ func Generate(outdir, pkg, name, abiJsonFilename string, mock bool) error { func init() { rootCmd.Flags().String("package", "contract", "package name") rootCmd.Flags().String("name", "", "contract name") - rootCmd.Flags().String("abi", "example.json", "abi json") + rootCmd.Flags().String("abi", "", "abi json") rootCmd.Flags().String("outdir", "", "output dir") rootCmd.Flags().Bool("mock", false, "generate mock") viper.AutomaticEnv() diff --git a/cmd/cligen/.gitignore b/cmd/cligen/.gitignore deleted file mode 100644 index ae65203..0000000 --- a/cmd/cligen/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -cligen -example/token*.go -example/*.json -example/example diff --git a/cmd/cligen/Makefile b/cmd/cligen/Makefile deleted file mode 100644 index 688d3ad..0000000 --- a/cmd/cligen/Makefile +++ /dev/null @@ -1,7 +0,0 @@ - -.PHONY: test -test: - (cd ../../hmcdk/genabi && cargo run ../../example/token/src/lib.rs) > example/token.json - go build - ./cligen --outdir example --name token --package main --abi example/token.json - (cd example && go build) diff --git a/cmd/cligen/example/main.go b/cmd/cligen/example/main.go deleted file mode 100644 index 7db7776..0000000 --- a/cmd/cligen/example/main.go +++ /dev/null @@ -1,32 +0,0 @@ -package main - -import ( - "fmt" - "github.com/spf13/cobra" - "github.com/spf13/viper" - "os" - "strings" -) - -var rootCmd = &cobra.Command{ - Use: "example", - Short: "Example CLI", -} - -const ( - TokenContractAddress = "0x3b74892E655c9E2e47f3442Ef64dA6766fd2a62c" - TokenCallerAddress = "0x933062aC91b12b27A88F0d8F00BE9eD0513f0D14" -) - -func init() { - rootCmd.AddCommand(TokenCmd(TokenContractAddress, TokenCallerAddress)) - viper.AutomaticEnv() - viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) -} - -func main() { - if err := rootCmd.Execute(); err != nil { - _, _ = fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} diff --git a/cmd/cligen/main.go b/cmd/cligen/main.go index b0b41d2..1ab4b67 100644 --- a/cmd/cligen/main.go +++ b/cmd/cligen/main.go @@ -42,13 +42,13 @@ func Generate(outdir, pkg, name, abiJsonFilename string) error { } else if src, err := clibind.Bind(pkg, name, string(abiJson)); err != nil { return err } else { - if err := os.MkdirAll(outdir, 0700); err != nil { + if err := os.MkdirAll(outdir, 0755); err != nil { return err } - if err := ioutil.WriteFile(path.Join(outdir, name+".go"), []byte(boundSrc), 0700); err != nil { + if err := ioutil.WriteFile(path.Join(outdir, name+".go"), []byte(boundSrc), 0644); err != nil { return err } - if err := ioutil.WriteFile(path.Join(outdir, name+"cmd.go"), []byte(src), 0700); err != nil { + if err := ioutil.WriteFile(path.Join(outdir, name+"cmd.go"), []byte(src), 0644); err != nil { return err } return nil @@ -59,7 +59,7 @@ func Generate(outdir, pkg, name, abiJsonFilename string) error { func init() { rootCmd.Flags().String("package", "contract", "package name") rootCmd.Flags().String("name", "", "contract name") - rootCmd.Flags().String("abi", "example.json", "abi json") + rootCmd.Flags().String("abi", "", "abi json") rootCmd.Flags().String("outdir", "", "output dir") viper.AutomaticEnv() viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) From 934344a9cf3b3b4a325dfba139871fb270fe3f9f Mon Sep 17 00:00:00 2001 From: Kiyoshi Nakao Date: Wed, 27 Nov 2019 15:44:33 +0900 Subject: [PATCH 23/24] XXX --- hmcdk/genabi/src/argument.rs | 1 + hmcdk/genabi/src/function.rs | 68 ++++++++++++------------ hmcdk/genabi/src/main.rs | 1 + tests/contracts/contract_test/src/lib.rs | 12 ++--- 4 files changed, 42 insertions(+), 40 deletions(-) diff --git a/hmcdk/genabi/src/argument.rs b/hmcdk/genabi/src/argument.rs index 8a134a7..2b3049c 100644 --- a/hmcdk/genabi/src/argument.rs +++ b/hmcdk/genabi/src/argument.rs @@ -7,6 +7,7 @@ use std::fmt::Display; pub enum ArgumentError { UnrecognizedType, UnsupportedType(String), + InvalidFunction(String) } #[derive(Clone, Serialize, Deserialize, Debug)] diff --git a/hmcdk/genabi/src/function.rs b/hmcdk/genabi/src/function.rs index 8ea1fca..5512e64 100644 --- a/hmcdk/genabi/src/function.rs +++ b/hmcdk/genabi/src/function.rs @@ -61,45 +61,45 @@ fn from_item_fn(f: &ItemFn) -> Result, ArgumentError> { let mut is_readonly = false; let fn_name = f.sig.ident.to_string(); for a in &f.attrs { - let s = a.path.segments.last(); - match s { - Some(s) => { - if s.ident == "contract" { - is_contract = true; - let ident: syn::Ident = match a.parse_args() { - Ok(ident) => ident, - Err(_) => continue - }; - if ident == "readonly" { - is_readonly = true + if a.path.segments.len() == 1 { + let s = a.path.segments.last(); + match s { + Some(s) => { + if s.ident == "contract" { + is_contract = true; + let ident: syn::Ident = match a.parse_args() { + Ok(ident) => ident, + Err(err) => return Err(ArgumentError::InvalidFunction(err.to_string())) + }; + if ident == "readonly" { + is_readonly = true + } } } + None => {} } - None => {} } } - let maybe_args = f - .sig - .inputs - .iter() - .map(|input| get_argument_from_arg(input)); - let func = match is_contract { - true => { - let rt = get_return_type(&f.sig.output)?; - let args = maybe_args.filter_map(Result::ok).collect::>(); - let f = Function { - r#type: "function".to_string(), - name: fn_name, - simulate: is_readonly, - inputs: args, - outputs: match rt { - Some(rt) => [rt].to_vec(), - None => [].to_vec(), - }, - }; - Some(f) - } - false => None, + let func = if is_contract { + let maybe_args = f + .sig + .inputs + .iter() + .map(|input| get_argument_from_arg(input)); + let rt = get_return_type(&f.sig.output)?; + let args = maybe_args.filter_map(Result::ok).collect::>(); + Some(Function { + r#type: "function".to_string(), + name: fn_name, + simulate: is_readonly, + inputs: args, + outputs: match rt { + Some(rt) => [rt].to_vec(), + None => [].to_vec(), + }, + }) + } else { + None }; Ok(func) } diff --git a/hmcdk/genabi/src/main.rs b/hmcdk/genabi/src/main.rs index 0b278bb..a09461b 100644 --- a/hmcdk/genabi/src/main.rs +++ b/hmcdk/genabi/src/main.rs @@ -33,6 +33,7 @@ impl Display for Error { IncorrectUsage => write!(f, "Usage: dump-syntax path/to/filename.rs"), ArgError(UnrecognizedType) => write!(f, "unrecognized arg type"), ArgError(UnsupportedType(x)) => write!(f, "unsupported arg type: {}", x), + ArgError(InvalidFunction(x)) => write!(f, "invalid function: {}", x), ReadFile(error) => write!(f, "Unable to read file: {}", error), InternalError => write!(f, "internal error"), } diff --git a/tests/contracts/contract_test/src/lib.rs b/tests/contracts/contract_test/src/lib.rs index f6941c9..b364cab 100644 --- a/tests/contracts/contract_test/src/lib.rs +++ b/tests/contracts/contract_test/src/lib.rs @@ -37,7 +37,7 @@ pub fn check_signature(msg_hash: Vec, sig: Vec) -> R { Ok(Some(call_check_signature()?)) } -#[contract] +#[contract()] pub fn test_read_uncommitted_state() -> R { let b = [0u8; 255]; write_state("key".as_bytes(), &b); @@ -50,7 +50,7 @@ pub fn test_read_uncommitted_state() -> R { } } -#[contract] +#[contract()] pub fn test_write_state(key: Vec, value: Vec) -> R { write_state(&key, &value); Ok(None) @@ -65,7 +65,7 @@ pub fn test_read_state(key: Vec) -> R> { Ok(Some(value)) } -#[contract] +#[contract()] pub fn test_read_write_state(key: Vec, value: Vec) -> R { // read a value, but nop read_state::>(&key); @@ -74,7 +74,7 @@ pub fn test_read_write_state(key: Vec, value: Vec) -> R { Ok(None) } -#[contract] +#[contract()] pub fn test_write_to_same_key(key: Vec, value1: Vec, value2: Vec) -> R { // read a value, but nop read_state::>(&key); @@ -85,7 +85,7 @@ pub fn test_write_to_same_key(key: Vec, value1: Vec, value2: Vec) -> Ok(None) } -#[contract] +#[contract()] pub fn test_write_to_multiple_key(key1: Vec, value1: Vec, key2: Vec, value2: Vec) -> R { // read a value, but nop read_state::>(&key1); @@ -107,7 +107,7 @@ pub fn test_sha256(msg: Vec) -> R> { Ok(Some(sha256(&msg)?.to_vec())) } -#[contract] +#[contract()] pub fn test_emit_event(msg0: Vec, msg1: Vec) -> R> { let name0 = "test-event-name-0"; let name1 = "test-event-name-1"; From 677722551d651dac79a92cc547d632d3173b61e6 Mon Sep 17 00:00:00 2001 From: Kiyoshi Nakao Date: Tue, 10 Dec 2019 15:46:16 +0900 Subject: [PATCH 24/24] simplify get_assignment_from_arg() --- hmcdk/codegen/src/lib.rs | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/hmcdk/codegen/src/lib.rs b/hmcdk/codegen/src/lib.rs index dd7820d..3ae3f9b 100644 --- a/hmcdk/codegen/src/lib.rs +++ b/hmcdk/codegen/src/lib.rs @@ -5,33 +5,26 @@ use quote::quote; use std::ops::Deref; use syn::{parse_macro_input, parse_quote, FnArg, Ident, ItemFn, Pat, Stmt, Type}; -fn get_assignment_from_name_and_type( - name: &Ident, - ty: &Type, - index: usize, -) -> Result { - match ty { - Type::Path(_type_path) => { - let a = parse_quote! { - let #name: #ty = get_arg(#index).unwrap(); - }; - Ok(a) - } - _ => Err("invalid arg type".to_string()), - } -} - fn get_assignment_from_arg(arg: &FnArg, index: usize) -> Result<(&Ident, Stmt), String> { match arg { - FnArg::Typed(pat_type) => match &pat_type.pat.deref() { - Pat::Ident(pat) => { - let pat = &pat.ident; - match get_assignment_from_name_and_type(pat, pat_type.ty.deref(), index) { - Ok(stmt) => Ok((pat, stmt)), - Err(err) => Err(err), + FnArg::Typed(pat_type) => { + let pat = pat_type.pat.deref(); + match pat { + Pat::Ident(pat) => { + let pat = &pat.ident; + let ty = pat_type.ty.deref(); + match ty { + Type::Path(_type_path) => { + let stmt = parse_quote! { + let #pat: #ty = get_arg(#index).unwrap(); + }; + Ok((pat, stmt)) + } + _ => Err("invalid arg type".to_string()), + } } + _ => Err("no parameter name".to_string()), } - _ => Err("no parameter name".to_string()), }, FnArg::Receiver(_receiver) => Err("receiver not supported".to_string()), }