Skip to content

Commit

Permalink
Merge pull request #33 from Bit-Nation/develop
Browse files Browse the repository at this point in the history
[dapp] first version of the DApp engine
  • Loading branch information
florianlenz authored Jun 17, 2018
2 parents e2c60fd + 688bed6 commit 33f461a
Show file tree
Hide file tree
Showing 26 changed files with 1,213 additions and 53 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ list:
@$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | xargs
proto:
protoc --go_out=. api/pb/*.proto
protoc --go_out=. dapp/registry/pb/*.proto
deps:
go get github.com/whyrusleeping/gx
go get github.com/whyrusleeping/gx-go
Expand Down
6 changes: 3 additions & 3 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ type UpStream interface {
// Create new api with given client
func New(client UpStream) *API {
return &API{
lock: sync.Mutex{},
requests: map[string]chan*Response{},
client: client,
lock: sync.Mutex{},
requests: map[string]chan *Response{},
client: client,
}
}

Expand Down
57 changes: 28 additions & 29 deletions api/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ package api
import (
"testing"
"time"

pb "github.com/Bit-Nation/panthalassa/api/pb"
require "github.com/stretchr/testify/require"
proto "github.com/golang/protobuf/proto"

require "github.com/stretchr/testify/require"
)

type testUpStream struct {
Expand All @@ -23,59 +22,59 @@ func TestAPI_addAndCutRequestWorks(t *testing.T) {

req := pb.Request{}
req.RequestID = "hi"

// api
api := New(&testUpStream{})

// make sure request doesn't exist
_, exist := api.requests["hi"]
require.False(t, exist)

api.addRequest(&req)

// make sure request does exist
_, exist = api.requests["hi"]
require.True(t, exist)

// now cut request our of the stack and make sure it was removed
api.cutRequest("hi")
_, exist = api.requests["hi"]
require.False(t, exist)

}

func TestRequestResponse(t *testing.T) {
func TestRequestResponse(t *testing.T) {

dataChan := make(chan string)

var receivedRequestID string

// api
api := New(&testUpStream{
sendFn: func(data string) {
dataChan <- data
},
})

go func() {
select {
case data := <-dataChan:
req := &pb.Request{}
if err := proto.Unmarshal([]byte(data), req); err != nil {
panic(err)
}
receivedRequestID = req.RequestID
out := api.Respond(req.RequestID, &pb.Response{
RequestID: req.RequestID,
}, nil, time.Second)
if out != nil {
panic("expected nil but got: " + out.Error())
}
case data := <-dataChan:
req := &pb.Request{}
if err := proto.Unmarshal([]byte(data), req); err != nil {
panic(err)
}
receivedRequestID = req.RequestID
out := api.Respond(req.RequestID, &pb.Response{
RequestID: req.RequestID,
}, nil, time.Second)
if out != nil {
panic("expected nil but got: " + out.Error())
}
}
}()

resp, err := api.request(&pb.Request{}, time.Second)
require.Nil(t, err)
require.Equal(t, resp.Msg.RequestID, receivedRequestID)
}

}
2 changes: 1 addition & 1 deletion api/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ package api
// to the request and response protobufs
// you can then extend the api struct
// if you e.g. would like to implement the DHT CRUD you can create a new file
// called `dht.go` in the api folder and start to implement the requests
// called `dht.go` in the api folder and start to implement the requests
5 changes: 3 additions & 2 deletions crypto/aes/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ package aes
import (
"crypto/hmac"
"crypto/sha256"
"github.com/kataras/iris/core/errors"
"github.com/stretchr/testify/require"
"errors"
"testing"

require "github.com/stretchr/testify/require"
)

func TestVersionOneOfMac(t *testing.T) {
Expand Down
71 changes: 71 additions & 0 deletions dapp/dapp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package dapp

import (
"encoding/hex"
"fmt"

module "github.com/Bit-Nation/panthalassa/dapp/module"
logger "github.com/op/go-logging"
otto "github.com/robertkrimen/otto"
)

type DApp struct {
vm *otto.Otto
logger *logger.Logger
app *JsonRepresentation
closeChan chan<- *JsonRepresentation
}

// close DApp
func (d *DApp) Close() {
d.vm.Interrupt <- func() {
d.logger.Info(fmt.Sprintf("shutting down: %s (%s)", hex.EncodeToString(d.app.SignaturePublicKey), d.app.Name))
d.closeChan <- d.app
}
}

func (d *DApp) ID() string {
return hex.EncodeToString(d.app.SignaturePublicKey)
}

// will start a DApp based on the given config file
//
func New(l *logger.Logger, app *JsonRepresentation, vmModules []module.Module, closer chan<- *JsonRepresentation) (*DApp, error) {

// check if app is valid
valid, err := app.VerifySignature()
if err != nil {
return nil, err
}
if !valid {
return nil, InvalidSignature
}

// create VM
vm := otto.New()
vm.Interrupt = make(chan func(), 1)

// register all vm modules
for _, m := range vmModules {
if err := m.Register(vm); err != nil {
return nil, err
}
}

dApp := &DApp{
vm: vm,
logger: l,
app: app,
closeChan: closer,
}

go func() {
_, err := vm.Run(app.Code)
if err != nil {
l.Error(err)
closer <- app
}
}()

return dApp, nil
}
59 changes: 59 additions & 0 deletions dapp/dapp_representation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package dapp

import (
"bytes"
"encoding/json"
"errors"

mh "github.com/multiformats/go-multihash"
ed25519 "golang.org/x/crypto/ed25519"
)

var InvalidSignature = errors.New("failed to verify signature for DApp")

// JSON Representation of published DApp
type JsonRepresentation struct {
Name string `json:"name"`
Code string `json:"code"`
SignaturePublicKey []byte `json:"signature_public_key"`
Signature []byte `json:"signature"`
}

// hash the published DApp
func (r JsonRepresentation) Hash() ([]byte, error) {

buff := bytes.NewBuffer([]byte(r.Name))

if _, err := buff.Write([]byte(r.Code)); err != nil {
return nil, err
}

if _, err := buff.Write(r.SignaturePublicKey); err != nil {
return nil, err
}

multiHash, err := mh.Sum(buff.Bytes(), mh.SHA3_256, -1)
if err != nil {
return nil, err
}

return multiHash, nil

}

// verify if this published DApp
// was signed with the attached public key
func (r JsonRepresentation) VerifySignature() (bool, error) {

hash, err := r.Hash()
if err != nil {
return false, err
}

return ed25519.Verify(r.SignaturePublicKey, hash, r.Signature), nil

}

func (r JsonRepresentation) Marshal() ([]byte, error) {
return json.Marshal(r)
}
75 changes: 75 additions & 0 deletions dapp/dapp_representation_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package dapp

import (
"bytes"
"crypto/rand"
"golang.org/x/crypto/ed25519"
"testing"

mh "github.com/multiformats/go-multihash"
require "github.com/stretchr/testify/require"
)

func TestDAppRepresentationHash(t *testing.T) {

pub, _, err := ed25519.GenerateKey(rand.Reader)
require.Nil(t, err)

rep := JsonRepresentation{
Name: "Send / Receive Money",
Code: `var wallet = "0x930aa9a843266bdb02847168d571e7913907dd84"`,
SignaturePublicKey: pub,
}

// calculate hash manually
// name + code + signature public key
buff := bytes.NewBuffer([]byte(rep.Name))

_, err = buff.Write([]byte(rep.Code))
require.Nil(t, err)

_, err = buff.Write([]byte(rep.SignaturePublicKey))
require.Nil(t, err)

expectedHash, err := mh.Sum(buff.Bytes(), mh.SHA3_256, -1)
require.Nil(t, err)

// calculate hash
calculateHash, err := rep.Hash()
require.Nil(t, err)

// check if hashes match
require.Equal(t, string(expectedHash), string(calculateHash))

}

func TestDAppVerifySignature(t *testing.T) {

pub, priv, err := ed25519.GenerateKey(rand.Reader)
require.Nil(t, err)

rep := JsonRepresentation{
Name: "Send / Receive Money",
Code: `var wallet = "0x930aa9a843266bdb02847168d571e7913907dd84"`,
SignaturePublicKey: pub,
}

// validate signature
// should be invalid since it doesn't exist
valid, err := rep.VerifySignature()
require.Nil(t, err)
require.False(t, valid)

// hash the representation
calculatedHash, err := rep.Hash()
require.Nil(t, err)

// sign representation
rep.Signature = ed25519.Sign(priv, calculatedHash)

// validate signature
valid, err = rep.VerifySignature()
require.Nil(t, err)
require.True(t, valid)

}
Loading

0 comments on commit 33f461a

Please sign in to comment.