-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #33 from Bit-Nation/develop
[dapp] first version of the DApp engine
- Loading branch information
Showing
26 changed files
with
1,213 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
|
||
} |
Oops, something went wrong.