feat: adjust validation and wasm module

move wasm lib to validation module
wasm instance now need imports to create
This commit is contained in:
levi9311 2020-04-16 19:56:01 +08:00
parent 3e602dcd07
commit d1af9adfef
11 changed files with 96 additions and 124 deletions

View File

@ -233,8 +233,11 @@ func (exec *BlockExecutor) applyTransaction(i int, tx *pb.Transaction) ([]byte,
instance = boltvm.New(ctx, exec.validationEngine)
case pb.TransactionData_XVM:
ctx := vm.NewContext(tx, uint64(i), tx.Data, exec.ledger, exec.logger)
var err error
instance, err = wasm.New(ctx)
imports, err := wasm.EmptyImports()
if err != nil {
return nil, err
}
instance, err = wasm.New(ctx, imports)
if err != nil {
return nil, err
}

View File

@ -2,7 +2,7 @@ package validator
import (
"github.com/meshplus/bitxhub/internal/ledger"
"github.com/meshplus/bitxhub/pkg/vm/wasm/wasmlib"
"github.com/meshplus/bitxhub/internal/validator/validatorlib"
"github.com/sirupsen/logrus"
)
@ -22,11 +22,11 @@ func NewFabV14Validator(ledger ledger.Ledger, logger logrus.FieldLogger) *FabV14
// Verify will check whether the transaction info is valid
func (vlt *FabV14Validator) Verify(address, from string, proof []byte, validators string) (bool, error) {
vInfo, err := wasmlib.UnmarshalValidatorInfo([]byte(validators))
vInfo, err := validatorlib.UnmarshalValidatorInfo([]byte(validators))
if err != nil {
return false, err
}
err = wasmlib.ValidateV14(proof, []byte(vInfo.Policy), vInfo.ConfByte, vInfo.Cid)
err = validatorlib.ValidateV14(proof, []byte(vInfo.Policy), vInfo.ConfByte, vInfo.Cid)
if err != nil {
return false, err
}

View File

@ -1,4 +1,4 @@
package wasmlib
package validatorlib
// #include <stdlib.h>
//

View File

@ -1,13 +1,8 @@
package wasmlib
package validatorlib
// #include <stdlib.h>
//
// extern int32_t fabric_validate_v13(void *context, long long proof_ptr, long long validator_ptr);
import "C"
import (
"encoding/json"
"fmt"
"unsafe"
"github.com/gogo/protobuf/proto"
mb "github.com/hyperledger/fabric-protos-go/msp"
@ -16,28 +11,8 @@ import (
"github.com/hyperledger/fabric/common/cauthdsl"
"github.com/hyperledger/fabric/msp"
"github.com/hyperledger/fabric/protoutil"
"github.com/wasmerio/go-ext-wasm/wasmer"
)
//export fabric_validate_v13
func fabric_validate_v13(context unsafe.Pointer, proof_ptr int64, validator_ptr int64) int32 {
ctx := wasmer.IntoInstanceContext(context)
data := ctx.Data().(map[int]int)
memory := ctx.Memory()
proof := memory.Data()[proof_ptr : proof_ptr+int64(data[int(proof_ptr)])]
validator := memory.Data()[validator_ptr : validator_ptr+int64(data[int(validator_ptr)])]
vInfo, err := UnmarshalValidatorInfo(validator)
if err != nil {
return 0
}
err = ValidateV14(proof, []byte(vInfo.Policy), vInfo.ConfByte, vInfo.Cid)
if err != nil {
return 0
}
return 1
}
type valiadationArtifacts struct {
rwset []byte
prp []byte
@ -210,11 +185,3 @@ func (ds *dynamicDeserializer) DeserializeIdentity(serializedIdentity []byte) (m
func (ds *dynamicDeserializer) IsWellFormed(identity *mb.SerializedIdentity) error {
return ds.mspm.IsWellFormed(identity)
}
func (im *Imports) importFabricV13() {
var err error
im.imports, err = im.imports.Append("fabric_validate_v13", fabric_validate_v13, C.fabric_validate_v13)
if err != nil {
return
}
}

View File

@ -0,0 +1,38 @@
package validatorlib
// #include <stdlib.h>
//
// extern int32_t fabric_validate_v13(void *context, long long proof_ptr, long long validator_ptr);
import "C"
import (
"unsafe"
"github.com/wasmerio/go-ext-wasm/wasmer"
)
//export fabric_validate_v13
func fabric_validate_v13(context unsafe.Pointer, proof_ptr int64, validator_ptr int64) int32 {
ctx := wasmer.IntoInstanceContext(context)
data := ctx.Data().(map[int]int)
memory := ctx.Memory()
proof := memory.Data()[proof_ptr : proof_ptr+int64(data[int(proof_ptr)])]
validator := memory.Data()[validator_ptr : validator_ptr+int64(data[int(validator_ptr)])]
vInfo, err := UnmarshalValidatorInfo(validator)
if err != nil {
return 0
}
err = ValidateV14(proof, []byte(vInfo.Policy), vInfo.ConfByte, vInfo.Cid)
if err != nil {
return 0
}
return 1
}
func (im *Imports) importFabricV13() {
var err error
im.imports, err = im.imports.Append("fabric_validate_v13", fabric_validate_v13, C.fabric_validate_v13)
if err != nil {
return
}
}

View File

@ -1,4 +1,4 @@
package wasmlib
package validatorlib
import (
"github.com/wasmerio/go-ext-wasm/wasmer"

View File

@ -7,6 +7,7 @@ import (
"github.com/meshplus/bitxhub-kit/types"
"github.com/meshplus/bitxhub-model/pb"
"github.com/meshplus/bitxhub/internal/ledger"
"github.com/meshplus/bitxhub/internal/validator/validatorlib"
"github.com/meshplus/bitxhub/pkg/vm"
"github.com/meshplus/bitxhub/pkg/vm/wasm"
"github.com/sirupsen/logrus"
@ -60,7 +61,11 @@ func (vlt *WasmValidator) initRule(address, from string, proof []byte, validator
}
wasmCtx := vm.NewContext(vlt.tx, 0, vlt.tx.Data, vlt.ledger, vlt.logger)
wasm, err := wasm.New(wasmCtx)
imports, err := validatorlib.New()
if err != nil {
return err
}
wasm, err := wasm.New(wasmCtx, imports)
if err != nil {
return err
}

View File

@ -11,7 +11,6 @@ import (
"github.com/meshplus/bitxhub-kit/types"
"github.com/meshplus/bitxhub-model/pb"
"github.com/meshplus/bitxhub/pkg/vm"
"github.com/meshplus/bitxhub/pkg/vm/wasm/wasmlib"
"github.com/wasmerio/go-ext-wasm/wasmer"
)
@ -23,18 +22,13 @@ var _ vm.VM = (*Wasm)(nil)
var instances = make(map[string]wasmer.Instance)
func getInstance(code []byte) (wasmer.Instance, error) {
func getInstance(code []byte, imports *wasmer.Imports) (wasmer.Instance, error) {
ret := sha256.Sum256(code)
v, ok := instances[string(ret[:])]
if ok {
return v, nil
}
imports, err := wasmlib.New()
if err != nil {
return wasmer.Instance{}, err
}
instance, err := wasmer.NewInstanceWithImports(code, imports)
if err != nil {
return wasmer.Instance{}, err
@ -66,7 +60,7 @@ type Contract struct {
}
// New creates a wasm vm instance
func New(ctx *vm.Context) (*Wasm, error) {
func New(ctx *vm.Context, imports *wasmer.Imports) (*Wasm, error) {
wasm := &Wasm{
ctx: ctx,
}
@ -90,7 +84,7 @@ func New(ctx *vm.Context) (*Wasm, error) {
return wasm, fmt.Errorf("contract byte is empty")
}
instance, err := getInstance(contract.Code)
instance, err := getInstance(contract.Code, imports)
if err != nil {
return nil, err
}
@ -101,6 +95,10 @@ func New(ctx *vm.Context) (*Wasm, error) {
return wasm, nil
}
func EmptyImports() (*wasmer.Imports, error) {
return wasmer.NewImports(), nil
}
// Run let the wasm vm excute or deploy the smart contract which depends on whether the callee is empty
func (w *Wasm) Run(input []byte) (ret []byte, err error) {
if w.ctx.Callee == (types.Address{}) {

View File

@ -13,6 +13,7 @@ import (
"github.com/meshplus/bitxhub-kit/types"
"github.com/meshplus/bitxhub-model/pb"
"github.com/meshplus/bitxhub/internal/ledger"
"github.com/meshplus/bitxhub/internal/validator/validatorlib"
"github.com/meshplus/bitxhub/pkg/storage/leveldb"
"github.com/meshplus/bitxhub/pkg/vm"
"github.com/stretchr/testify/assert"
@ -117,7 +118,9 @@ func initFabricContext(t *testing.T, name string) *vm.Context {
func TestDeploy(t *testing.T) {
ctx := initCreateContext(t, "create")
wasm, err := New(ctx)
imports, err := EmptyImports()
require.Nil(t, err)
wasm, err := New(ctx, imports)
require.Nil(t, err)
_, err = wasm.deploy()
@ -126,7 +129,9 @@ func TestDeploy(t *testing.T) {
func TestExecute(t *testing.T) {
ctx := initCreateContext(t, "execute")
wasm, err := New(ctx)
imports, err := EmptyImports()
require.Nil(t, err)
wasm, err := New(ctx, imports)
require.Nil(t, err)
ret, err := wasm.deploy()
@ -150,7 +155,9 @@ func TestExecute(t *testing.T) {
TransactionData: data,
Ledger: ctx.Ledger,
}
wasm1, err := New(ctx1)
imports1, err := validatorlib.New()
require.Nil(t, err)
wasm1, err := New(ctx1, imports1)
require.Nil(t, err)
result, err := wasm1.Run(payload)
@ -160,7 +167,9 @@ func TestExecute(t *testing.T) {
func TestWasm_RunFabValidation(t *testing.T) {
ctx := initFabricContext(t, "execute")
wasm, err := New(ctx)
imports, err := EmptyImports()
require.Nil(t, err)
wasm, err := New(ctx, imports)
require.Nil(t, err)
ret, err := wasm.deploy()
@ -188,7 +197,9 @@ func TestWasm_RunFabValidation(t *testing.T) {
TransactionData: data,
Ledger: ctx.Ledger,
}
wasm1, err := New(ctx1)
imports1, err := validatorlib.New()
require.Nil(t, err)
wasm1, err := New(ctx1, imports1)
require.Nil(t, err)
result, err := wasm1.Run(payload)
@ -220,7 +231,9 @@ func BenchmarkRunFabValidation(b *testing.B) {
TransactionData: data,
Ledger: ldg,
}
wasm, err := New(ctx)
imports, err := EmptyImports()
require.Nil(b, err)
wasm, err := New(ctx, imports)
require.Nil(b, err)
ret, err := wasm.deploy()
@ -246,7 +259,9 @@ func BenchmarkRunFabValidation(b *testing.B) {
Ledger: ctx.Ledger,
}
for i := 0; i < b.N; i++ {
wasm1, err := New(ctx1)
imports1, err := validatorlib.New()
require.Nil(b, err)
wasm1, err := New(ctx1, imports1)
require.Nil(b, err)
result, err := wasm1.Run(payload)
@ -259,7 +274,9 @@ func BenchmarkRunFabValidation(b *testing.B) {
func TestWasm_RunValidation(t *testing.T) {
ctx := initValidationContext(t, "execute")
wasm, err := New(ctx)
imports, err := EmptyImports()
require.Nil(t, err)
wasm, err := New(ctx, imports)
require.Nil(t, err)
ret, err := wasm.deploy()
@ -285,7 +302,9 @@ func TestWasm_RunValidation(t *testing.T) {
TransactionData: data,
Ledger: ctx.Ledger,
}
wasm1, err := New(ctx1)
imports1, err := validatorlib.New()
require.Nil(t, err)
wasm1, err := New(ctx1, imports1)
require.Nil(t, err)
result, err := wasm1.Run(payload)
@ -295,7 +314,9 @@ func TestWasm_RunValidation(t *testing.T) {
func TestWasm_RunWithoutMethod(t *testing.T) {
ctx := initCreateContext(t, "execute_without_method")
wasm, err := New(ctx)
imports, err := EmptyImports()
require.Nil(t, err)
wasm, err := New(ctx, imports)
require.Nil(t, err)
ret, err := wasm.deploy()
@ -319,7 +340,9 @@ func TestWasm_RunWithoutMethod(t *testing.T) {
TransactionData: data,
Ledger: ctx.Ledger,
}
wasm1, err := New(ctx1)
imports1, err := validatorlib.New()
require.Nil(t, err)
wasm1, err := New(ctx1, imports1)
require.Nil(t, err)
_, err = wasm1.Run(payload)

View File

@ -1,62 +0,0 @@
package wasmlib
import (
"io/ioutil"
"testing"
"github.com/golang/protobuf/proto"
m "github.com/hyperledger/fabric-protos-go/msp"
"github.com/hyperledger/fabric/protoutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGetPolicyEnvelope(t *testing.T) {
_, err := GetPolicyEnvelope("OR(AND('A.member', 'B.member'), OR('C.admin', 'D.member'))")
assert.NoError(t, err)
}
func TestPayloadUnmarshal(t *testing.T) {
bytes, err := ioutil.ReadFile("../testdata/proof")
require.Nil(t, err)
cap, err := protoutil.UnmarshalChaincodeActionPayload(bytes)
require.Nil(t, err)
prp := cap.Action.ProposalResponsePayload
signatureSet := []*protoutil.SignedData{}
for _, endorsement := range cap.Action.Endorsements {
data := make([]byte, len(prp)+len(endorsement.Endorser))
copy(data, prp)
copy(data[len(prp):], endorsement.Endorser)
signatureSet = append(signatureSet, &protoutil.SignedData{
// set the data that is signed; concatenation of proposal response bytes and endorser ID
Data: data,
// set the identity that signs the message: it's the endorser
Identity: endorsement.Endorser,
// set the signature
Signature: endorsement.Signature})
}
sId := &m.SerializedIdentity{}
err = proto.Unmarshal(signatureSet[0].Identity, sId)
require.Nil(t, err)
}
func TestUnmarshalValidatorInfo(t *testing.T) {
vBytes, err := ioutil.ReadFile("../testdata/validator")
require.Nil(t, err)
_, err = UnmarshalValidatorInfo(vBytes)
require.Nil(t, err)
}
func TestValidateV14(t *testing.T) {
vBytes, err := ioutil.ReadFile("../testdata/validator")
require.Nil(t, err)
proof, err := ioutil.ReadFile("../testdata/proof")
require.Nil(t, err)
v, err := UnmarshalValidatorInfo(vBytes)
require.Nil(t, err)
err = ValidateV14(proof, []byte(v.Policy), v.ConfByte, v.Cid)
require.Nil(t, err)
}