Commit f9e9df1e authored by harrylee's avatar harrylee

Merge branch 'master' of gitlab.33.cn:link33/sidecar

parents 1bfbe86e aeda6e51
Pipeline #8211 canceled with stages
......@@ -120,6 +120,8 @@ fmt_go: fmt_shell ## go fmt
fmt: fmt_proto fmt_shell ## go fmt
@go fmt ./...
@find . -name '*.go' -not -path "./vendor/*" | xargs goimports -l -w
gofumpt:
@gofumpt -l -w .
pb:
......@@ -165,7 +167,7 @@ build-dep:
aligner:
@aligner -r -c "//" -e ".go" -i ./internal/repo/a_repo-packr.go comment
goimports:fmt
goimports:
@CGO_ENABLED=1 goimports-reviser -dir-path ./ -project-name gitlab.33.cn/link33/sidecar -ignore-dir mock -rm-unused -set-alias -format
aligner-check:
......
......@@ -81,6 +81,7 @@ require (
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect
github.com/herumi/bls-eth-go-binary v0.0.0-20210917013441-d37c07cfda4e // indirect
github.com/huin/goupnp v1.0.0 // indirect
github.com/hyperledger/fabric v2.0.1+incompatible // indirect
github.com/hyperledger/fabric-amcl v0.0.0-20200424173818-327c9e2cf77a // indirect
......@@ -170,6 +171,7 @@ require (
github.com/spf13/jwalterweatherman v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
github.com/supranational/blst v0.3.6 // indirect
github.com/sykesm/zap-logfmt v0.0.3 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 // indirect
github.com/tidwall/match v1.0.3 // indirect
......
......@@ -347,6 +347,8 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/herumi/bls-eth-go-binary v0.0.0-20210917013441-d37c07cfda4e h1:wCMygKUQhmcQAjlk2Gquzq6dLmyMv2kF+llRspoRgrk=
github.com/herumi/bls-eth-go-binary v0.0.0-20210917013441-d37c07cfda4e/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c=
github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U=
......@@ -678,7 +680,6 @@ github.com/meshplus/bitxhub-kit v1.2.1-0.20210524063043-9afae78ac098 h1:/E1isgGc
github.com/meshplus/bitxhub-kit v1.2.1-0.20210524063043-9afae78ac098/go.mod h1:wrEdhHp1tktzdwcWb4bOxYsVc+KkcrYL18IYWYeumPQ=
github.com/meshplus/bitxhub-model v1.0.0-rc3/go.mod h1:ZCctQIYTlE3vJ8Lhkrgs9bWwNA+Dw4JzojOSIzLVU6E=
github.com/meshplus/bitxhub-model v1.1.1/go.mod h1:lUl9vPZXM9tP+B0ABRW/2eOW/6KCmjFTdoiTj5Vut/A=
github.com/meshplus/bitxhub-model v1.2.1-0.20210524063354-5d48e2fee178 h1:z8KGkI7DBGX9c4dUZNMT7kfBvUqZNqGNuI7uyKLZ5Tc=
github.com/meshplus/bitxhub-model v1.2.1-0.20210524063354-5d48e2fee178/go.mod h1:vwJ+sHPUyA2JELmUUDBol+7zA+7GcqutxzqXjsN0QLA=
github.com/meshplus/bitxid v0.0.0-20210412025850-e0eaf0f9063a h1:c4ESPDa60Jd4zfzZIGGTyzhfaVM3vKN+xV2G9BwIDGQ=
github.com/meshplus/bitxid v0.0.0-20210412025850-e0eaf0f9063a/go.mod h1:vAldSRfDe2Qo7exsSTbchVmZWXPY7fhWQrRw18QJHho=
......@@ -936,6 +937,8 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/supranational/blst v0.3.6 h1:a24cPQB0qYpXPMZx177aapCM50/YrTMt/TKAUa7TzdM=
github.com/supranational/blst v0.3.6/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
github.com/sykesm/zap-logfmt v0.0.3 h1:3Wrhf7+I9JEUD8B6KPtDAr9j2jrS0/EPLy7GCE1t/+U=
github.com/sykesm/zap-logfmt v0.0.3/go.mod h1:AuBd9xQjAe3URrWT1BBDk2v2onAZHkZkWRMiYZXiZWA=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
......
......@@ -95,31 +95,10 @@ type Client interface {
// Get link33's signatures specified by id and type.
GetMultiSigns(id string, typ pb.GetMultiSignsRequest_Type) (*pb.SignResponse, error)
// Get link33 TPS during block [begin, end]
GetTPS(begin, end uint64) (uint64, error)
// GetPendingNonceByAccount returns the latest nonce of an account in the pending status,
// and it should be the nonce for next transaction
GetPendingNonceByAccount(account string) (uint64, error)
// Delete node according to its pid
DelVPNode(pid string) (*pb.Response, error)
// IPFSPutFromLocal puts local file to ipfs network
IPFSPutFromLocal(localfPath string) (*pb.Response, error)
// IPFSGet gets from ipfs network
IPFSGet(path string) (*pb.Response, error)
// IPFSGetToLocal gets from ipfs and saves to local file path
IPFSGetToLocal(path string, localfPath string) (*pb.Response, error)
// Check whethe there is a master sidecar connect to the link33.
CheckMasterSidecar(address string) (*pb.Response, error)
// Set the master sidecar connect to the link33.
SetMasterSidecar(address string, index string, timeout int64) (*pb.Response, error)
// Update the master sidecar status
HeartBeat(address string, index string) (*pb.Response, error)
}
......
......@@ -50,12 +50,6 @@ func WithPrivateKey(key crypto.PrivateKey) Option {
}
}
func WithIPFSInfo(addrs []string) Option {
return func(config *config) {
config.ipfsAddrs = addrs
}
}
func WithTimeoutLimit(limit time.Duration) Option {
return func(config *config) {
config.timeoutLimit = limit
......
......@@ -9,10 +9,10 @@ import (
reflect "reflect"
gomock "github.com/golang/mock/gomock"
rpcx "gitlab.33.cn/link33/sidecar/hub/client"
pb "gitlab.33.cn/link33/sidecar/model/pb"
crypto "github.com/meshplus/bitxhub-kit/crypto"
types "github.com/meshplus/bitxhub-kit/types"
rpcx "gitlab.33.cn/link33/sidecar/hub/client"
pb "gitlab.33.cn/link33/sidecar/model/pb"
)
// MockClient is a mock of Client interface.
......@@ -38,36 +38,6 @@ func (m *MockClient) EXPECT() *MockClientMockRecorder {
return m.recorder
}
// CheckMasterSidecar mocks base method.
func (m *MockClient) CheckMasterSidecar(address string) (*pb.Response, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "CheckMasterSidecar", address)
ret0, _ := ret[0].(*pb.Response)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// CheckMasterSidecar indicates an expected call of CheckMasterSidecar.
func (mr *MockClientMockRecorder) CheckMasterSidecar(address interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckMasterSidecar", reflect.TypeOf((*MockClient)(nil).CheckMasterSidecar), address)
}
// DelVPNode mocks base method.
func (m *MockClient) DelVPNode(pid string) (*pb.Response, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "DelVPNode", pid)
ret0, _ := ret[0].(*pb.Response)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// DelVPNode indicates an expected call of DelVPNode.
func (mr *MockClientMockRecorder) DelVPNode(pid interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelVPNode", reflect.TypeOf((*MockClient)(nil).DelVPNode), pid)
}
// DeployContract mocks base method.
func (m *MockClient) DeployContract(contract []byte, opts *rpcx.TransactOpts) (*types.Address, error) {
m.ctrl.T.Helper()
......@@ -281,21 +251,6 @@ func (mr *MockClientMockRecorder) GetReceipt(hash interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReceipt", reflect.TypeOf((*MockClient)(nil).GetReceipt), hash)
}
// GetTPS mocks base method.
func (m *MockClient) GetTPS(begin, end uint64) (uint64, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetTPS", begin, end)
ret0, _ := ret[0].(uint64)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetTPS indicates an expected call of GetTPS.
func (mr *MockClientMockRecorder) GetTPS(begin, end interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTPS", reflect.TypeOf((*MockClient)(nil).GetTPS), begin, end)
}
// GetTransaction mocks base method.
func (m *MockClient) GetTransaction(hash string) (*pb.GetTransactionResponse, error) {
m.ctrl.T.Helper()
......@@ -341,51 +296,6 @@ func (mr *MockClientMockRecorder) HeartBeat(address, index interface{}) *gomock.
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeartBeat", reflect.TypeOf((*MockClient)(nil).HeartBeat), address, index)
}
// IPFSGet mocks base method.
func (m *MockClient) IPFSGet(path string) (*pb.Response, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "IPFSGet", path)
ret0, _ := ret[0].(*pb.Response)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// IPFSGet indicates an expected call of IPFSGet.
func (mr *MockClientMockRecorder) IPFSGet(path interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IPFSGet", reflect.TypeOf((*MockClient)(nil).IPFSGet), path)
}
// IPFSGetToLocal mocks base method.
func (m *MockClient) IPFSGetToLocal(path, localfPath string) (*pb.Response, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "IPFSGetToLocal", path, localfPath)
ret0, _ := ret[0].(*pb.Response)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// IPFSGetToLocal indicates an expected call of IPFSGetToLocal.
func (mr *MockClientMockRecorder) IPFSGetToLocal(path, localfPath interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IPFSGetToLocal", reflect.TypeOf((*MockClient)(nil).IPFSGetToLocal), path, localfPath)
}
// IPFSPutFromLocal mocks base method.
func (m *MockClient) IPFSPutFromLocal(localfPath string) (*pb.Response, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "IPFSPutFromLocal", localfPath)
ret0, _ := ret[0].(*pb.Response)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// IPFSPutFromLocal indicates an expected call of IPFSPutFromLocal.
func (mr *MockClientMockRecorder) IPFSPutFromLocal(localfPath interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IPFSPutFromLocal", reflect.TypeOf((*MockClient)(nil).IPFSPutFromLocal), localfPath)
}
// InvokeBVMContract mocks base method.
func (m *MockClient) InvokeBVMContract(address *types.Address, method string, opts *rpcx.TransactOpts, args ...*pb.Arg) (*pb.Receipt, error) {
m.ctrl.T.Helper()
......@@ -491,21 +401,6 @@ func (mr *MockClientMockRecorder) SendView(tx interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendView", reflect.TypeOf((*MockClient)(nil).SendView), tx)
}
// SetMasterSidecar mocks base method.
func (m *MockClient) SetMasterSidecar(address, index string, timeout int64) (*pb.Response, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SetMasterSidecar", address, index, timeout)
ret0, _ := ret[0].(*pb.Response)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SetMasterSidecar indicates an expected call of SetMasterSidecar.
func (mr *MockClientMockRecorder) SetMasterSidecar(address, index, timeout interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetMasterSidecar", reflect.TypeOf((*MockClient)(nil).SetMasterSidecar), address, index, timeout)
}
// SetPrivateKey mocks base method.
func (m *MockClient) SetPrivateKey(arg0 crypto.PrivateKey) {
m.ctrl.T.Helper()
......
......@@ -40,7 +40,7 @@ func NewPort(client plugins.Client, cryptor txcrypto.Cryptor, logger logrus.Fiel
client: client,
cryptor: cryptor,
logger: logger,
recvCh: make(chan *pb.IBTP, 1024),
recvCh: make(chan *pb.IBTP, port.MaxCapacity),
ctx: ctx,
cancel: cancel,
msgCh: make(chan *pb.Message, port.Capacity),
......@@ -97,7 +97,7 @@ func (a *appChain) ExecuteIBTP(ibtp *pb.IBTP) (*pb.IBTP, error) {
}).Info("Apply tx")
switch ibtp.Type {
case pb.IBTP_INTERCHAIN:
case pb.IBTP_INTERCHAIN, pb.IBTP_ROLLBACK:
return a.applyInterchainIBTP(ibtp)
case pb.IBTP_RECEIPT_SUCCESS, pb.IBTP_RECEIPT_FAILURE:
err := a.applyReceiptIBTP(ibtp)
......
......@@ -47,7 +47,6 @@ func (a *appChain) Send(msg *pb.Message) (*pb.Message, error) {
return nil, errors.New("ibtp wrong")
}
if ibtp.Type == pb.IBTP_RECEIPT_FAILURE || pb.IBTP_RECEIPT_SUCCESS == ibtp.Type {
//
//TODO 默认路由
ix := pb.IBTPX{
Ibtp: ibtp,
......@@ -87,7 +86,19 @@ func (a *appChain) ListenIBTPX() <-chan *pb.Message {
select {
case ibtp := <-ibtpCh:
// TODO ibtp to ibtpx
data, _ := ibtp.Marshal()
// TODO 默认路由
ix := pb.IBTPX{
Ibtp: ibtp,
Mode: repo.DirectMode,
RouteSign: []string{},
RouteMethod: router.Single,
RouteMethodArg: []string{},
IsValid: false, // TODO
}
data, err := ix.Marshal()
if err != nil {
a.logger.Error("appchain ListenIBTPX Err: ", err)
}
msg := pb.Msg(pb.Message_IBTP_SEND, true, data)
a.msgCh <- msg
case <-a.ctx.Done():
......
......@@ -3,9 +3,10 @@ package rulemgr
import (
"sync"
"github.com/meshplus/bitxhub-core/validator"
"github.com/meshplus/bitxhub-kit/storage"
"github.com/sirupsen/logrus"
"gitlab.33.cn/link33/sidecar/pkg/validator"
)
type Rule struct {
......
......@@ -8,9 +8,9 @@ import (
reflect "reflect"
gomock "github.com/golang/mock/gomock"
appchain_mgr "github.com/meshplus/bitxhub-core/appchain-mgr"
syncer "gitlab.33.cn/link33/sidecar/internal/syncer"
pb "gitlab.33.cn/link33/sidecar/model/pb"
appchain_mgr "github.com/meshplus/bitxhub-core/appchain-mgr"
)
// MockSyncer is a mock of Syncer interface.
......
......@@ -33,9 +33,9 @@ func (m *IBTP) Hash() *types.Hash {
func (m *IBTP) Category() IBTP_Category {
switch m.Type {
case IBTP_INTERCHAIN, IBTP_ASSET_EXCHANGE_INIT, IBTP_ASSET_EXCHANGE_REDEEM, IBTP_ASSET_EXCHANGE_REFUND:
case IBTP_INTERCHAIN, IBTP_ROLLBACK:
return IBTP_REQUEST
case IBTP_RECEIPT_SUCCESS, IBTP_RECEIPT_FAILURE, IBTP_ASSET_EXCHANGE_RECEIPT:
case IBTP_RECEIPT_SUCCESS, IBTP_RECEIPT_FAILURE, IBTP_RECEIPT_ROLLBACK:
return IBTP_RESPONSE
}
return IBTP_UNKNOWN
......
......@@ -28,33 +28,27 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type IBTP_Type int32
const (
IBTP_INTERCHAIN IBTP_Type = 0
IBTP_RECEIPT_SUCCESS IBTP_Type = 1
IBTP_RECEIPT_FAILURE IBTP_Type = 2
IBTP_ASSET_EXCHANGE_INIT IBTP_Type = 3
IBTP_ASSET_EXCHANGE_REDEEM IBTP_Type = 4
IBTP_ASSET_EXCHANGE_REFUND IBTP_Type = 5
IBTP_ASSET_EXCHANGE_RECEIPT IBTP_Type = 6
IBTP_INTERCHAIN IBTP_Type = 0
IBTP_RECEIPT_SUCCESS IBTP_Type = 1
IBTP_RECEIPT_FAILURE IBTP_Type = 2
IBTP_ROLLBACK IBTP_Type = 3
IBTP_RECEIPT_ROLLBACK IBTP_Type = 4
)
var IBTP_Type_name = map[int32]string{
0: "INTERCHAIN",
1: "RECEIPT_SUCCESS",
2: "RECEIPT_FAILURE",
3: "ASSET_EXCHANGE_INIT",
4: "ASSET_EXCHANGE_REDEEM",
5: "ASSET_EXCHANGE_REFUND",
6: "ASSET_EXCHANGE_RECEIPT",
3: "ROLLBACK",
4: "RECEIPT_ROLLBACK",
}
var IBTP_Type_value = map[string]int32{
"INTERCHAIN": 0,
"RECEIPT_SUCCESS": 1,
"RECEIPT_FAILURE": 2,
"ASSET_EXCHANGE_INIT": 3,
"ASSET_EXCHANGE_REDEEM": 4,
"ASSET_EXCHANGE_REFUND": 5,
"ASSET_EXCHANGE_RECEIPT": 6,
"INTERCHAIN": 0,
"RECEIPT_SUCCESS": 1,
"RECEIPT_FAILURE": 2,
"ROLLBACK": 3,
"RECEIPT_ROLLBACK": 4,
}
func (x IBTP_Type) String() string {
......@@ -460,44 +454,42 @@ func init() {
func init() { proto.RegisterFile("ibtp.proto", fileDescriptor_7576a0a5bf0190a3) }
var fileDescriptor_7576a0a5bf0190a3 = []byte{
// 587 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x53, 0xcf, 0x6e, 0xd3, 0x3e,
0x1c, 0xaf, 0xdb, 0xb4, 0x4d, 0xbf, 0xed, 0xb6, 0xc8, 0xfb, 0xfd, 0x86, 0x99, 0x50, 0x14, 0x7a,
0x80, 0x70, 0xe9, 0xa1, 0x20, 0xee, 0x5d, 0xe6, 0xb1, 0x08, 0x96, 0x0d, 0x27, 0x15, 0xdc, 0xaa,
0x24, 0xcd, 0xaa, 0x88, 0x2d, 0x8e, 0x1c, 0x0f, 0xd1, 0xb7, 0xe0, 0x3d, 0x78, 0x11, 0x8e, 0x3b,
0x72, 0x44, 0xdb, 0x89, 0x0b, 0xcf, 0x80, 0xec, 0xb4, 0xeb, 0xf8, 0x73, 0xf3, 0xe7, 0x9f, 0xbf,
0x89, 0xfd, 0x31, 0x40, 0x9e, 0xc8, 0x72, 0x54, 0x0a, 0x2e, 0x39, 0x6e, 0x96, 0xc9, 0x7e, 0x3f,
0x89, 0xab, 0x3c, 0xad, 0x89, 0xe1, 0xcf, 0x16, 0x18, 0xfe, 0x41, 0x74, 0x86, 0x31, 0x18, 0xe7,
0x82, 0x5f, 0x12, 0xe4, 0x20, 0xb7, 0xc7, 0xf4, 0x1a, 0x6f, 0x43, 0x53, 0x72, 0xd2, 0xd4, 0x4c,
0x53, 0x72, 0xfc, 0x1f, 0xb4, 0x0b, 0x5e, 0xa4, 0x19, 0x69, 0x39, 0xc8, 0x35, 0x58, 0x0d, 0xf0,
0x63, 0x30, 0xe4, 0xb2, 0xcc, 0x88, 0xe1, 0x20, 0x77, 0x7b, 0xbc, 0x35, 0x2a, 0x93, 0x91, 0xda,
0x71, 0x14, 0x2d, 0xcb, 0x8c, 0x69, 0x09, 0x3f, 0x82, 0x9e, 0xcc, 0x2f, 0xb3, 0x4a, 0xc6, 0x97,
0x25, 0x69, 0x3b, 0xc8, 0x6d, 0xb1, 0x0d, 0xa1, 0xb6, 0x2d, 0x05, 0xe7, 0xe7, 0xa4, 0xe3, 0x20,
0x77, 0xc0, 0x6a, 0x80, 0x09, 0x74, 0xcb, 0x78, 0x79, 0xc1, 0xe3, 0x39, 0xe9, 0x6a, 0x7e, 0x0d,
0xf1, 0x33, 0x68, 0x2f, 0x04, 0xbf, 0x2a, 0x89, 0xe9, 0x20, 0xb7, 0x3f, 0xde, 0x55, 0x13, 0x43,
0x29, 0xf2, 0x62, 0x31, 0xcd, 0x0b, 0xf9, 0xf2, 0xc5, 0x49, 0x5c, 0xb2, 0xda, 0xa1, 0x36, 0xf9,
0x98, 0x89, 0x2a, 0xe7, 0x05, 0xe9, 0xe9, 0xdf, 0x58, 0x43, 0x35, 0x34, 0xfb, 0x24, 0x45, 0x4c,
0xa0, 0x1e, 0xaa, 0xc1, 0xf0, 0x0b, 0x02, 0x43, 0x7d, 0x37, 0xde, 0x06, 0xf0, 0x83, 0x88, 0x32,
0xef, 0x78, 0xe2, 0x07, 0x56, 0x03, 0xef, 0xc2, 0x0e, 0xa3, 0x1e, 0xf5, 0xcf, 0xa2, 0x59, 0x38,
0xf5, 0x3c, 0x1a, 0x86, 0x16, 0xba, 0x4f, 0x1e, 0x4d, 0xfc, 0x37, 0x53, 0x46, 0xad, 0x26, 0x7e,
0x00, 0xbb, 0x93, 0x30, 0xa4, 0xd1, 0x8c, 0xbe, 0xf7, 0x8e, 0x27, 0xc1, 0x2b, 0x3a, 0xf3, 0x03,
0x3f, 0xb2, 0x5a, 0xf8, 0x21, 0xfc, 0xff, 0x87, 0xc0, 0xe8, 0x21, 0xa5, 0x27, 0x96, 0xf1, 0x4f,
0xe9, 0x68, 0x1a, 0x1c, 0x5a, 0x6d, 0xbc, 0x0f, 0x7b, 0x7f, 0x49, 0x7a, 0xa4, 0xd5, 0x19, 0x8e,
0xc1, 0xf4, 0x62, 0x99, 0x2d, 0xb8, 0x58, 0xe2, 0x3e, 0x74, 0x19, 0x7d, 0x3b, 0xa5, 0x61, 0x64,
0x35, 0xf0, 0x00, 0x4c, 0x46, 0xc3, 0xb3, 0xd3, 0x20, 0xa4, 0x16, 0x52, 0xd2, 0x34, 0x78, 0x1d,
0x9c, 0xbe, 0x0b, 0xac, 0xe6, 0x70, 0x72, 0x77, 0xac, 0xea, 0x56, 0xb2, 0x22, 0x15, 0xcb, 0x52,
0x66, 0x73, 0x7d, 0xef, 0x26, 0xdb, 0x10, 0xea, 0xe8, 0x52, 0x5e, 0xc8, 0xac, 0x90, 0xba, 0x01,
0x03, 0xb6, 0x86, 0xc3, 0x1f, 0xe8, 0x4e, 0xc2, 0x4f, 0x60, 0xa7, 0x12, 0xe9, 0x4c, 0x41, 0x11,
0xa7, 0x72, 0x96, 0xcf, 0x57, 0x0d, 0xda, 0xaa, 0x44, 0xea, 0xad, 0x58, 0x7f, 0xae, 0x7c, 0xf3,
0x4a, 0xfe, 0xe6, 0xab, 0x7b, 0xb5, 0x35, 0xaf, 0xe4, 0x3d, 0x9f, 0xaa, 0xe1, 0x55, 0x91, 0xea,
0x86, 0xa9, 0x1a, 0x5e, 0x15, 0xa9, 0xe2, 0x62, 0xb1, 0xa8, 0x88, 0xe1, 0xb4, 0xdc, 0x01, 0xd3,
0x6b, 0xbc, 0x0f, 0x66, 0x1a, 0x5f, 0x5c, 0x24, 0x71, 0xfa, 0x41, 0x17, 0xaa, 0xc7, 0xee, 0x30,
0xde, 0x83, 0x8e, 0xf2, 0x78, 0x09, 0xe9, 0xe8, 0xc4, 0x0a, 0xa9, 0x8c, 0xe0, 0xab, 0x4c, 0xb7,
0xce, 0xac, 0xf1, 0x3a, 0xc3, 0x12, 0x62, 0x6e, 0x32, 0x2c, 0x19, 0x3e, 0x85, 0xb6, 0x2a, 0x73,
0x85, 0x6d, 0x68, 0xab, 0x77, 0x54, 0x11, 0xe4, 0xb4, 0xdc, 0xfe, 0xd8, 0x5c, 0xd7, 0x9c, 0xd5,
0xf4, 0x01, 0xf9, 0x7a, 0x63, 0xa3, 0xeb, 0x1b, 0x1b, 0x7d, 0xbf, 0xb1, 0xd1, 0xe7, 0x5b, 0xbb,
0x71, 0x7d, 0x6b, 0x37, 0xbe, 0xdd, 0xda, 0x8d, 0xa4, 0xa3, 0x5f, 0xda, 0xf3, 0x5f, 0x01, 0x00,
0x00, 0xff, 0xff, 0x98, 0x2d, 0x3a, 0x6f, 0x88, 0x03, 0x00, 0x00,
// 551 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x53, 0xcd, 0x6e, 0xd3, 0x4c,
0x14, 0xcd, 0xc4, 0x4e, 0xe2, 0xdc, 0xa4, 0xad, 0x35, 0xad, 0x3e, 0x8d, 0xaa, 0x4f, 0x96, 0xf1,
0x02, 0xcc, 0x26, 0x8b, 0x80, 0xd8, 0xa7, 0x96, 0x11, 0x56, 0x8b, 0x5b, 0xc6, 0x89, 0x58, 0x56,
0xfe, 0x6b, 0x64, 0xd1, 0x7a, 0x46, 0xe3, 0x29, 0x22, 0x6f, 0xc1, 0x53, 0xf0, 0x2c, 0x2c, 0xbb,
0x64, 0x89, 0xda, 0x15, 0x6f, 0x81, 0x66, 0x1c, 0x27, 0x65, 0x37, 0xe7, 0xdc, 0x73, 0xee, 0xf5,
0xcc, 0x3d, 0x06, 0xa8, 0x32, 0xc9, 0x67, 0x5c, 0x30, 0xc9, 0x70, 0x9f, 0x67, 0xa7, 0x93, 0x2c,
0x6d, 0xaa, 0xbc, 0x25, 0xbc, 0x1f, 0x06, 0x98, 0xd1, 0xd9, 0xf2, 0x0a, 0x63, 0x30, 0x6f, 0x04,
0xbb, 0x23, 0xc8, 0x45, 0xfe, 0x98, 0xea, 0x33, 0x3e, 0x84, 0xbe, 0x64, 0xa4, 0xaf, 0x99, 0xbe,
0x64, 0xf8, 0x04, 0x06, 0x35, 0xab, 0xf3, 0x92, 0x18, 0x2e, 0xf2, 0x4d, 0xda, 0x02, 0xfc, 0x02,
0x4c, 0xb9, 0xe1, 0x25, 0x31, 0x5d, 0xe4, 0x1f, 0xce, 0x0f, 0x66, 0x3c, 0x9b, 0xa9, 0x8e, 0xb3,
0xe5, 0x86, 0x97, 0x54, 0x97, 0xf0, 0xff, 0x30, 0x96, 0xd5, 0x5d, 0xd9, 0xc8, 0xf4, 0x8e, 0x93,
0x81, 0x8b, 0x7c, 0x83, 0xee, 0x09, 0xd5, 0x96, 0x0b, 0xc6, 0x6e, 0xc8, 0xd0, 0x45, 0xfe, 0x94,
0xb6, 0x00, 0x13, 0x18, 0xf1, 0x74, 0x73, 0xcb, 0xd2, 0x82, 0x8c, 0x34, 0xdf, 0x41, 0xfc, 0x1a,
0x06, 0x6b, 0xc1, 0xee, 0x39, 0xb1, 0x5c, 0xe4, 0x4f, 0xe6, 0xc7, 0x6a, 0x62, 0x22, 0x45, 0x55,
0xaf, 0x57, 0x55, 0x2d, 0xdf, 0xbd, 0xfd, 0x98, 0x72, 0xda, 0x2a, 0x54, 0x93, 0xaf, 0xa5, 0x68,
0x2a, 0x56, 0x93, 0xb1, 0xbe, 0x46, 0x07, 0xd5, 0xd0, 0xf2, 0x9b, 0x14, 0x29, 0x81, 0x76, 0xa8,
0x06, 0x5e, 0x01, 0xa6, 0xfa, 0x6c, 0x7c, 0x08, 0x10, 0xc5, 0xcb, 0x90, 0x06, 0x1f, 0x16, 0x51,
0x6c, 0xf7, 0xf0, 0x31, 0x1c, 0xd1, 0x30, 0x08, 0xa3, 0xab, 0xe5, 0x75, 0xb2, 0x0a, 0x82, 0x30,
0x49, 0x6c, 0xf4, 0x9c, 0x7c, 0xbf, 0x88, 0x2e, 0x56, 0x34, 0xb4, 0xfb, 0x78, 0x0a, 0x16, 0xbd,
0xbc, 0xb8, 0x38, 0x5b, 0x04, 0xe7, 0xb6, 0x81, 0x4f, 0xc0, 0xee, 0x24, 0x3b, 0xd6, 0xf4, 0xe6,
0x60, 0x05, 0xa9, 0x2c, 0xd7, 0x4c, 0x6c, 0xf0, 0x04, 0x46, 0x34, 0xfc, 0xb4, 0x0a, 0x93, 0xa5,
0xdd, 0xd3, 0xe6, 0x30, 0xb9, 0xba, 0x8c, 0x93, 0xd0, 0x46, 0xaa, 0xb4, 0x8a, 0xcf, 0xe3, 0xcb,
0xcf, 0xb1, 0xdd, 0xf7, 0x16, 0xbb, 0xe7, 0x50, 0xaf, 0x59, 0xd6, 0xb9, 0xd8, 0x70, 0x59, 0x16,
0x7a, 0x5f, 0x16, 0xdd, 0x13, 0xea, 0xca, 0x39, 0xab, 0x65, 0x59, 0x4b, 0xbd, 0xb9, 0x29, 0xed,
0xa0, 0xf7, 0x07, 0xed, 0x4a, 0xf8, 0x25, 0x1c, 0x35, 0x22, 0xbf, 0x56, 0x50, 0xa4, 0xb9, 0xbc,
0xae, 0x8a, 0xed, 0xe6, 0x0f, 0x1a, 0x91, 0x07, 0x5b, 0x36, 0x2a, 0x94, 0xae, 0x68, 0xe4, 0x3f,
0xba, 0x36, 0x0f, 0x07, 0x45, 0x23, 0x9f, 0xe9, 0x54, 0x7c, 0xee, 0xeb, 0x5c, 0x27, 0x43, 0xc5,
0xe7, 0xbe, 0xce, 0x15, 0x97, 0x8a, 0x75, 0x43, 0x4c, 0xd7, 0xf0, 0xa7, 0x54, 0x9f, 0xf1, 0x29,
0x58, 0x79, 0x7a, 0x7b, 0x9b, 0xa5, 0xf9, 0x17, 0x1d, 0x84, 0x31, 0xdd, 0x61, 0xfc, 0x1f, 0x0c,
0x95, 0x26, 0xc8, 0xc8, 0x50, 0x3b, 0xb6, 0x48, 0x79, 0x04, 0xdb, 0x7a, 0x46, 0xad, 0xa7, 0xc3,
0x9d, 0x87, 0x66, 0xc4, 0xda, 0x7b, 0x68, 0xe6, 0xbd, 0x82, 0x81, 0x0a, 0x61, 0x83, 0x1d, 0x18,
0xa8, 0xfc, 0x37, 0x04, 0xb9, 0x86, 0x3f, 0x99, 0x5b, 0x5d, 0x3c, 0x69, 0x4b, 0x9f, 0x91, 0x9f,
0x8f, 0x0e, 0x7a, 0x78, 0x74, 0xd0, 0xef, 0x47, 0x07, 0x7d, 0x7f, 0x72, 0x7a, 0x0f, 0x4f, 0x4e,
0xef, 0xd7, 0x93, 0xd3, 0xcb, 0x86, 0xfa, 0x0f, 0x79, 0xf3, 0x37, 0x00, 0x00, 0xff, 0xff, 0xf4,
0x8e, 0xc3, 0xc2, 0x40, 0x03, 0x00, 0x00,
}
func (m *IBTP) Marshal() (dAtA []byte, err error) {
......
......@@ -7,13 +7,11 @@ import "basic.proto";
// Inter-blockchain Transfer Protocol
message IBTP {
enum Type {
INTERCHAIN = 0;
RECEIPT_SUCCESS = 1;
RECEIPT_FAILURE = 2;
ASSET_EXCHANGE_INIT = 3;
ASSET_EXCHANGE_REDEEM = 4;
ASSET_EXCHANGE_REFUND = 5;
ASSET_EXCHANGE_RECEIPT = 6;
INTERCHAIN = 0;
RECEIPT_SUCCESS = 1;
RECEIPT_FAILURE = 2;
ROLLBACK = 3;
RECEIPT_ROLLBACK = 4;
}
enum Category {
......@@ -62,4 +60,4 @@ message content {
message IBTPs {
repeated IBTP ibtps = 1;
}
\ No newline at end of file
}
......@@ -9,7 +9,7 @@ message IBTPX {
IBTP ibtp = 1;
// route mode
string mode = 2; // dirct、relay
repeated string routeSign = 3; //路由节点签名路径,主要是对data hash签名,主要是相互校验。sidecar节点之间相互校验。sidecar 节点需要注册到中继连上。还可以过滤已经发送过的交易、也可以作恶惩罚。
repeated string routeSign = 3; //路由节点签名路径,主要是对data hash签名,主要是相互校验。sidecar节点之间相互校验。sidecar 节点需要注册到中继连上。还可以过滤已经发送过的交易、也可以作恶惩罚。使用bls签名算法,聚合签名。
string routeMethod = 4; // single、multicast、broadcast、
repeated string routeMethodArg = 5; //路由节点,默认第一个节点。或者转发消息。
bool IsValid = 6;
......
package bls
import (
"github.com/herumi/bls-eth-go-binary/bls"
)
type Sign = bls.Sign
type SecretKey = bls.SecretKey
type PublicKey = bls.PublicKey
type PublicKeys = bls.PublicKeys
type ID = bls.ID
package bls
import (
"encoding/hex"
"testing"
"github.com/herumi/bls-eth-go-binary/bls"
)
func TestGetSafePublicKey(t *testing.T) {
if bls.Init(bls.BLS12_381) != nil {
t.Fatalf("Init")
}
var sec SecretKey
pub, err := sec.GetSafePublicKey()
if pub != nil || err == nil {
t.Fatalf("sec must be zero")
}
sec.SetByCSPRNG()
pub, err = sec.GetSafePublicKey()
if pub == nil || err != nil {
t.Fatalf("sec must be non-zero")
}
}
func TestEthDraft07(t *testing.T) {
secHex := "0000000000000000000000000000000000000000000000000000000000000001"
msgHex := "61736466"
sigHex := "b45a264e0d6f8614c4640ea97bae13effd3c74c4e200e3b1596d6830debc952602a7d210eca122dc4f596fa01d7f6299106933abd29477606f64588595e18349afe22ecf2aeeeb63753e88a42ef85b24140847e05620a28422f8c30f1d33b9aa"
ethSignOneTest(t, secHex, msgHex, sigHex)
}
func ethSignOneTest(t *testing.T, secHex string, msgHex string, sigHex string) {
var sec SecretKey
if sec.DeserializeHexStr(secHex) != nil {
t.Fatalf("bad sec")
}
var sig Sign
if sig.DeserializeHexStr(sigHex) != nil {
t.Logf("bad sig %v\n", sigHex)
return
}
pub := sec.GetPublicKey()
msg, _ := hex.DecodeString(msgHex)
sig = *sec.SignByte(msg)
if !sig.VerifyByte(pub, msg) {
t.Fatalf("bad verify %v %v", secHex, msgHex)
}
s := sig.SerializeToHexStr()
if s != sigHex {
t.Fatalf("bad sign\nL=%v\nR=%v\nsec=%v\nmsg=%v", s, sigHex, secHex, msgHex)
}
}
func TestBlsAggregateVerifyNoCheck(t *testing.T) {
nTbl := []int{1, 2, 15, 16, 17, 50}
for i := 0; i < len(nTbl); i++ {
blsAggregateVerifyNoCheckTestOne(t, nTbl[i])
}
}
func blsAggregateVerifyNoCheckTestOne(t *testing.T, n int) {
t.Logf("blsAggregateVerifyNoCheckTestOne %v\n", n)
pubs, sigs, msgs := makeMultiSig(n)
if !bls.AreAllMsgDifferent(msgs) {
t.Fatalf("bad msgs")
}
var aggSig Sign
aggSig.Aggregate(sigs)
if !aggSig.AggregateVerifyNoCheck(pubs, msgs) {
t.Fatalf("bad AggregateVerifyNoCheck 1")
}
msgs[1] = 1
if aggSig.AggregateVerifyNoCheck(pubs, msgs) {
t.Fatalf("bad AggregateVerifyNoCheck 2")
}
}
func makeMultiSig(n int) (pubs []PublicKey, sigs []Sign, msgs []byte) {
msgSize := 32
pubs = make([]PublicKey, n)
sigs = make([]Sign, n)
msgs = make([]byte, n*msgSize)
for i := 0; i < n; i++ {
var sec SecretKey
sec.SetByCSPRNG()
pubs[i] = *sec.GetPublicKey()
msgs[msgSize*i] = byte(i)
sigs[i] = *sec.SignByte(msgs[msgSize*i : msgSize*(i+1)])
}
return pubs, sigs, msgs
}
......@@ -152,18 +152,12 @@ func (g *GRPCClient) Initialize(configPath string, ID string, extra []byte) erro
ConfigPath: configPath,
Extra: extra,
})
if err != nil {
return err
}
return nil
return err
}
func (g *GRPCClient) Start() error {
_, err := g.client.Start(g.doneContext, &pb.Empty{})
if err != nil {
return err
}
return nil
return err
}
func (g *GRPCClient) Stop() error {
......
package validator
import (
"crypto/ecdsa"
"crypto/sha256"
"crypto/x509"
"encoding/asn1"
"encoding/pem"
"fmt"
"math/big"
"sync"
"github.com/sirupsen/logrus"
"gitlab.33.cn/link33/sidecar/pkg/validator/validatorlib"
)
// Validator is the instance that can use wasm to verify transaction validity
type FabSimValidator struct {
logger logrus.FieldLogger
pkMap *sync.Map
}
// New a validator instance
func NewFabSimValidator(logger logrus.FieldLogger) *FabSimValidator {
return &FabSimValidator{
logger: logger,
pkMap: &sync.Map{},
}
}
// Verify will check whether the transaction info is valid
func (vlt *FabSimValidator) Verify(address, from string, proof, payload []byte, validators string) (bool, error) {
artifact, err := validatorlib.PreCheck(proof, payload, "broker")
if err != nil {
return false, err
}
signatureSet := validatorlib.GetSignatureSet(artifact)
var pk *ecdsa.PublicKey
raw, ok := vlt.pkMap.Load(from)
if !ok {
pemCert, _ := pem.Decode([]byte(validators))
cert, err := x509.ParseCertificate(pemCert.Bytes)
if err != nil {
return false, err
}
pk = cert.PublicKey.(*ecdsa.PublicKey)
vlt.pkMap.Store(from, pk)
} else {
pk = raw.(*ecdsa.PublicKey)
}
r, s, err := unmarshalECDSASignature(signatureSet[0].Signature)
if err != nil {
return false, err
}
h := sha256.New()
_, err = h.Write(signatureSet[0].Data)
if err != nil {
return false, err
}
ret := h.Sum(nil)
isValid := ecdsa.Verify(pk, ret, r, s)
return isValid, nil
}
type ECDSASignature struct {
R, S *big.Int
}
func unmarshalECDSASignature(raw []byte) (*big.Int, *big.Int, error) {
sig := new(ECDSASignature)
_, err := asn1.Unmarshal(raw, sig)
if err != nil {
return nil, nil, fmt.Errorf("failed unmashalling signature [%s]", err)
}
// Validate sig
if sig.R == nil {
return nil, nil, fmt.Errorf("invalid signature, r must be different from nil")
}
if sig.S == nil {
return nil, nil, fmt.Errorf("invalid signature, s must be different from nil")
}
if sig.R.Sign() != 1 {
return nil, nil, fmt.Errorf("invalid signature, r must be larger than zero")
}
if sig.S.Sign() != 1 {
return nil, nil, fmt.Errorf("invalid signature, s must be larger than zero")
}
return sig.R, sig.S, nil
}
package validator
import (
"sort"
"sync"
"github.com/hyperledger/fabric/common/cauthdsl"
"github.com/hyperledger/fabric/common/policies"
mspi "github.com/hyperledger/fabric/msp"
"github.com/hyperledger/fabric/protoutil"
"github.com/sirupsen/logrus"
"gitlab.33.cn/link33/sidecar/pkg/validator/validatorlib"
)
// Validator is the instance that can use wasm to verify transaction validity
type FabV14Validator struct {
logger logrus.FieldLogger
evMap *sync.Map
peMap *sync.Map
ppMap *sync.Map
idMap *sync.Map
keyMap *sync.Map
}
// New a validator instance
func NewFabV14Validator(logger logrus.FieldLogger) *FabV14Validator {
return &FabV14Validator{
logger: logger,
evMap: &sync.Map{},
peMap: &sync.Map{},
ppMap: &sync.Map{},
idMap: &sync.Map{},
keyMap: &sync.Map{},
}
}
// Verify will check whether the transaction info is valid
func (vlt *FabV14Validator) Verify(address, from string, proof, payload []byte, validators string) (bool, error) {
var (
vInfo *validatorlib.ValidatorInfo
policy policies.Policy
err error
)
raw, ok := vlt.evMap.Load(from)
if !ok {
vInfo, err = validatorlib.UnmarshalValidatorInfo([]byte(validators))
if err != nil {
return false, err
}
vlt.evMap.Store(from, vInfo)
} else {
vInfo = raw.(*validatorlib.ValidatorInfo)
}
// Get the validation artifacts that help validate the chaincodeID and policy
artifact, err := validatorlib.PreCheck(proof, payload, vInfo.Cid)
if err != nil {
return false, err
}
signatureSet := validatorlib.GetSignatureSet(artifact)
raw, ok = vlt.ppMap.Load(vInfo.ChainId)
if !ok {
pe, err := validatorlib.NewPolicyEvaluator(vInfo.ConfByte)
if err != nil {
return false, err
}
pp := cauthdsl.NewPolicyProvider(pe.IdentityDeserializer)
policy, _, err = pp.NewPolicy([]byte(vInfo.Policy))
if err != nil {
return false, err
}
vlt.ppMap.Store(vInfo.ChainId, policy)
vlt.peMap.Store(vInfo.ChainId, pe)
} else {
policy = raw.(policies.Policy)
}
pe, _ := vlt.peMap.Load(vInfo.ChainId)
return vlt.EvaluateSignedData(signatureSet, pe.(*validatorlib.PolicyEvaluator).IdentityDeserializer, policy)
}
func (vlt *FabV14Validator) EvaluateSignedData(signedData []*protoutil.SignedData, identityDeserializer mspi.IdentityDeserializer, policy policies.Policy) (bool, error) {
idMap := map[string]struct{}{}
identities := make([]mspi.Identity, 0, len(signedData))
ids := make([]string, 0, len(signedData))
for _, sd := range signedData {
var (
identity mspi.Identity
err error
)
raw, ok := vlt.idMap.Load(string(sd.Identity))
if !ok {
identity, err = identityDeserializer.DeserializeIdentity(sd.Identity)
if err != nil {
continue
}
vlt.idMap.Store(string(sd.Identity), identity)
} else {
identity = raw.(mspi.Identity)
}
key := identity.GetIdentifier().Mspid + identity.GetIdentifier().Id
if _, ok := idMap[key]; ok {
continue
}
err = identity.Verify(sd.Data, sd.Signature)
if err != nil {
continue
}
idMap[key] = struct{}{}
ids = append(ids, key)
identities = append(identities, identity)
}
nids := sort.StringSlice(ids)
var idStr string
for _, id := range nids {
idStr = idStr + id
}
_, ok := vlt.keyMap.Load(idStr)
if !ok {
if err := policy.EvaluateIdentities(identities); err != nil {
return false, err
}
vlt.keyMap.Store(idStr, struct{}{})
return true, nil
}
return true, nil
}
// Code generated by MockGen. DO NOT EDIT.
// Source: validator.go
// Package mock_validator is a generated GoMock package.
package mock_validator
import (
reflect "reflect"
gomock "github.com/golang/mock/gomock"
types "github.com/meshplus/bitxhub-kit/types"
)
// MockEngine is a mock of Engine interface.
type MockEngine struct {
ctrl *gomock.Controller
recorder *MockEngineMockRecorder
}
// MockEngineMockRecorder is the mock recorder for MockEngine.
type MockEngineMockRecorder struct {
mock *MockEngine
}
// NewMockEngine creates a new mock instance.
func NewMockEngine(ctrl *gomock.Controller) *MockEngine {
mock := &MockEngine{ctrl: ctrl}
mock.recorder = &MockEngineMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockEngine) EXPECT() *MockEngineMockRecorder {
return m.recorder
}
// Validate mocks base method.
func (m *MockEngine) Validate(address, from string, proof, payload []byte, validators string) (bool, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Validate", address, from, proof, payload, validators)
ret0, _ := ret[0].(bool)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Validate indicates an expected call of Validate.
func (mr *MockEngineMockRecorder) Validate(address, from, proof, payload, validators interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Validate", reflect.TypeOf((*MockEngine)(nil).Validate), address, from, proof, payload, validators)
}
// MockValidator is a mock of Validator interface.
type MockValidator struct {
ctrl *gomock.Controller
recorder *MockValidatorMockRecorder
}
// MockValidatorMockRecorder is the mock recorder for MockValidator.
type MockValidatorMockRecorder struct {
mock *MockValidator
}
// NewMockValidator creates a new mock instance.
func NewMockValidator(ctrl *gomock.Controller) *MockValidator {
mock := &MockValidator{ctrl: ctrl}
mock.recorder = &MockValidatorMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockValidator) EXPECT() *MockValidatorMockRecorder {
return m.recorder
}
// Verify mocks base method.
func (m *MockValidator) Verify(address, from string, proof, payload []byte, validators string) (bool, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Verify", address, from, proof, payload, validators)
ret0, _ := ret[0].(bool)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Verify indicates an expected call of Verify.
func (mr *MockValidatorMockRecorder) Verify(address, from, proof, payload, validators interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Verify", reflect.TypeOf((*MockValidator)(nil).Verify), address, from, proof, payload, validators)
}
// MockLedger is a mock of Ledger interface.
type MockLedger struct {
ctrl *gomock.Controller
recorder *MockLedgerMockRecorder
}
// MockLedgerMockRecorder is the mock recorder for MockLedger.
type MockLedgerMockRecorder struct {
mock *MockLedger
}
// NewMockLedger creates a new mock instance.
func NewMockLedger(ctrl *gomock.Controller) *MockLedger {
mock := &MockLedger{ctrl: ctrl}
mock.recorder = &MockLedgerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockLedger) EXPECT() *MockLedgerMockRecorder {
return m.recorder
}
// GetCode mocks base method.
func (m *MockLedger) GetCode(arg0 *types.Address) []byte {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetCode", arg0)
ret0, _ := ret[0].([]byte)
return ret0
}
// GetCode indicates an expected call of GetCode.
func (mr *MockLedgerMockRecorder) GetCode(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCode", reflect.TypeOf((*MockLedger)(nil).GetCode), arg0)
}
package validator
import (
"sync"
"github.com/sirupsen/logrus"
)
const (
FabricRuleAddr = "0x00000000000000000000000000000000000000a0"
SimFabricRuleAddr = "0x00000000000000000000000000000000000000a1"
)
// Validator is the instance that can use wasm to verify transaction validity
type ValidationEngine struct {
instances *sync.Map
fabValidator Validator
simFabValidator Validator
ledger Ledger
logger logrus.FieldLogger
}
// New a validator instance
func NewValidationEngine(ledger Ledger, instances *sync.Map, logger logrus.FieldLogger) *ValidationEngine {
return &ValidationEngine{
ledger: ledger,
logger: logger,
fabValidator: NewFabV14Validator(logger),
simFabValidator: NewFabSimValidator(logger),
instances: instances,
}
}
// Verify will check whether the transaction info is valid
func (ve *ValidationEngine) Validate(address, from string, proof, payload []byte, validators string) (bool, error) {
vlt := ve.getValidator(address)
return vlt.Verify(address, from, proof, payload, validators)
}
func (ve *ValidationEngine) getValidator(address string) Validator {
if address == FabricRuleAddr {
return ve.fabValidator
}
if address == SimFabricRuleAddr {
return ve.simFabValidator
}
if ve.instances == nil {
ve.instances = &sync.Map{}
}
return NewWasmValidator(ve.ledger, ve.logger, ve.instances)
}
package validator
import (
"fmt"
"io/ioutil"
"testing"
"github.com/meshplus/bitxhub-kit/log"
"github.com/stretchr/testify/require"
"gitlab.33.cn/link33/sidecar/model/pb"
)
func TestFabV14ValidatorWasm_Verify(t *testing.T) {
logger := log.NewWithModule("validator")
v := NewValidationEngine(nil, nil, logger)
proof, err := ioutil.ReadFile("./testdata/proof")
require.Nil(t, err)
validators, err := ioutil.ReadFile("./testdata/validators")
require.Nil(t, err)
content := &pb.Content{
SrcContractId: "mychannel&transfer",
DstContractId: "0x668a209Dc6562707469374B8235e37b8eC25db08",
Func: "get",
Args: [][]byte{[]byte("Alice"), []byte("Alice"), []byte("1")},
Callback: "interchainConfirm",
}
bytes, err := content.Marshal()
require.Nil(t, err)
payload := &pb.Payload{
Encrypted: false,
Content: bytes,
}
body, err := payload.Marshal()
require.Nil(t, err)
ok, err := v.Validate(FabricRuleAddr, "0xe02d8fdacd59020d7f292ab3278d13674f5c404d", proof, body, string(validators))
require.NotNil(t, err)
require.False(t, ok)
}
func TestFabV14Validator_Verify(t *testing.T) {
logger := log.NewWithModule("validator")
v := NewValidationEngine(nil, nil, logger)
proof, err := ioutil.ReadFile("./testdata/proof")
require.Nil(t, err)
validators, err := ioutil.ReadFile("./testdata/validators")
require.Nil(t, err)
content := &pb.Content{
SrcContractId: "mychannel&transfer",
DstContractId: "0x668a209Dc6562707469374B8235e37b8eC25db08",
Func: "get",
Args: [][]byte{[]byte("Alice"), []byte("Alice"), []byte("1")},
Callback: "interchainConfirm",
}
bytes, err := content.Marshal()
require.Nil(t, err)
payload := &pb.Payload{
Encrypted: false,
Content: bytes,
}
body, err := payload.Marshal()
require.Nil(t, err)
ok, err := v.Validate(FabricRuleAddr, "0xe02d8fdacd59020d7f292ab3278d13674f5c404d", proof, body, string(validators))
require.NotNil(t, err)
require.False(t, ok)
}
func TestFabSimValidator_Verify(t *testing.T) {
logger := log.NewWithModule("validator")
v := NewValidationEngine(nil, nil, logger)
proof, err := ioutil.ReadFile("./testdata/proof_1.0.0_rc")
require.Nil(t, err)
validators, err := ioutil.ReadFile("./testdata/single_validator")
require.Nil(t, err)
content := &pb.Content{
SrcContractId: "mychannel&transfer",
DstContractId: "mychannel&transfer",
Func: "get",
Args: [][]byte{[]byte("Alice"), []byte("Alice"), []byte("1")},
Callback: "interchainConfirm",
}
bytes, err := content.Marshal()
require.Nil(t, err)
payload := &pb.Payload{
Encrypted: false,
Content: bytes,
}
body, err := payload.Marshal()
require.Nil(t, err)
ok, err := v.Validate(SimFabricRuleAddr, "0xe02d8fdacd59020d7f292ab3278d13674f5c404d", proof, body, string(validators))
require.Nil(t, err)
fmt.Println(ok)
}
func BenchmarkFabV14Validator_Verify(b *testing.B) {
logger := log.NewWithModule("validator")
proof, err := ioutil.ReadFile("./testdata/proof_1.0.0_rc")
require.Nil(b, err)
validators, err := ioutil.ReadFile("./testdata/validator_1.0.0_rc")
require.Nil(b, err)
content := &pb.Content{
SrcContractId: "mychannel&transfer",
DstContractId: "mychannel&transfer",
Func: "interchainCharge",
Args: [][]byte{[]byte("Alice"), []byte("Alice"), []byte("1")},
Callback: "interchainConfirm",
}
bytes, err := content.Marshal()
require.Nil(b, err)
payload := &pb.Payload{
Encrypted: false,
Content: bytes,
}
body, err := payload.Marshal()
require.Nil(b, err)
v := NewValidationEngine(nil, nil, logger)
ok, err := v.Validate(FabricRuleAddr, "0xe02d8fdacd59020d7f292ab3278d13674f5c404d", proof, body, string(validators))
require.Nil(b, err)
require.True(b, ok)
b.ResetTimer()
for i := 0; i < b.N; i++ {
ok, err := v.Validate(FabricRuleAddr, "0xe02d8fdacd59020d7f292ab3278d13674f5c404d", proof, body, string(validators))
require.Nil(b, err)
require.True(b, ok)
}
}
func BenchmarkFabSimValidator_Verify(b *testing.B) {
logger := log.NewWithModule("validator")
proof, err := ioutil.ReadFile("./testdata/proof_1.0.0_rc")
require.Nil(b, err)
validators, err := ioutil.ReadFile("./testdata/single_validator")
require.Nil(b, err)
content := &pb.Content{
SrcContractId: "mychannel&transfer",
DstContractId: "mychannel&transfer",
Func: "interchainCharge",
Args: [][]byte{[]byte("Alice"), []byte("Alice"), []byte("1")},
Callback: "interchainConfirm",
}
bytes, err := content.Marshal()
require.Nil(b, err)
payload := &pb.Payload{
Encrypted: false,
Content: bytes,
}
body, err := payload.Marshal()
require.Nil(b, err)
v := NewValidationEngine(nil, nil, logger)
b.ResetTimer()
for i := 0; i < b.N; i++ {
ok, err := v.Validate(SimFabricRuleAddr, "0xe02d8fdacd59020d7f292ab3278d13674f5c404d", proof, body, string(validators))
require.Nil(b, err)
require.True(b, ok)
}
}
func BenchmarkFabComplexValidator_Verify(b *testing.B) {
logger := log.NewWithModule("validator")
proof, err := ioutil.ReadFile("./testdata/proof_1.0.0_rc_complex")
require.Nil(b, err)
validators, err := ioutil.ReadFile("./testdata/validator_1.0.0_rc_complex")
require.Nil(b, err)
content := &pb.Content{
SrcContractId: "mychannel&transfer",
DstContractId: "mychannel&transfer",
Func: "interchainCharge",
Args: [][]byte{[]byte("Alice"), []byte("Alice"), []byte("1")},
Callback: "interchainConfirm",
}
bytes, err := content.Marshal()
require.Nil(b, err)
payload := &pb.Payload{
Encrypted: false,
Content: bytes,
}
body, err := payload.Marshal()
require.Nil(b, err)
v := NewValidationEngine(nil, nil, logger)
ok, err := v.Validate(FabricRuleAddr, "0xe02d8fdacd59020d7f292ab3278d13674f5c404d", proof, body, string(validators))
require.Nil(b, err)
require.True(b, ok)
b.ResetTimer()
for i := 0; i < b.N; i++ {
ok, err := v.Validate(FabricRuleAddr, "0xe02d8fdacd59020d7f292ab3278d13674f5c404d", proof, body, string(validators))
require.Nil(b, err)
require.True(b, ok)
}
}
package validator
import "github.com/meshplus/bitxhub-kit/types"
// Engine runs for validation
//go:generate mockgen -destination mock_validator/mock_engine.go -package mock_validator -source validator.go
type Engine interface {
Validate(address, from string, proof, payload []byte, validators string) (bool, error)
}
// Validator chooses specific method to verify transaction
type Validator interface {
Verify(address, from string, proof, payload []byte, validators string) (bool, error)
}
type Ledger interface {
// GetCode
GetCode(*types.Address) []byte
}
package validatorlib
// #include <stdlib.h>
//
// extern int32_t fabric_validate_v14(void *context, long long proof_ptr, long long validator_ptr, long long payload_ptr);
import "C"
import (
"unsafe"
"github.com/wasmerio/go-ext-wasm/wasmer"
)
//export fabric_validate_v14
func fabric_validate_v14(context unsafe.Pointer, proof_ptr int64, validator_ptr int64, payload_ptr int64) int32 {
ctx := wasmer.IntoInstanceContext(context)
ctxMap := ctx.Data().(map[string]interface{})
data := ctxMap["argmap"].(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)])]
payload := memory.Data()[payload_ptr : payload_ptr+int64(data[int(payload_ptr)])]
vInfo, err := UnmarshalValidatorInfo(validator)
if err != nil {
return 0
}
artifact, err := extractValidationArtifacts(proof)
if err != nil {
return 0
}
if err := ValidateChainCodeID(artifact.prp, vInfo.Cid); err != nil {
return 0
}
if err := ValidatePayload(artifact.payload, payload); err != nil {
return 0
}
signatureSet := GetSignatureSet(artifact)
pe, ok := ctxMap[FABRIC_EVALUATOR].(*PolicyEvaluator)
if !ok {
pe, err = NewPolicyEvaluator(vInfo.ConfByte)
if err != nil {
return 0
}
ctxMap[FABRIC_EVALUATOR] = pe
}
if err = pe.Evaluate([]byte(vInfo.Policy), signatureSet); err != nil {
return 0
}
return 1
}
func (im *Imports) importFabricV14() {
var err error
im.imports, err = im.imports.Append("fabric_validate_v14", fabric_validate_v14, C.fabric_validate_v14)
if err != nil {
return
}
}
package validatorlib
// #include <stdlib.h>
//
// extern int32_t ecdsa_verify(void *context, long long sig_ptr, long long digest_ptr, long long pubkey_ptr, int32_t opt);
import "C"
import (
"bytes"
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/x509"
"encoding/asn1"
"encoding/pem"
"fmt"
"math/big"
"unsafe"
"github.com/wasmerio/go-ext-wasm/wasmer"
)
type AlgorithmOption string
const (
// Secp256r1 secp256r1 algorithm
Secp256r1 AlgorithmOption = "Secp256r1"
)
type PrivateKey struct {
K *ecdsa.PrivateKey
}
// PublicKey ECDSA public key.
// never new(PublicKey), use NewPublicKey()
type PublicKey struct {
k *ecdsa.PublicKey
}
type ECDSASignature struct {
R, S *big.Int
}
//export ecdsa_verify
func ecdsa_verify(context unsafe.Pointer, sig_ptr int64, digest_ptr int64, pubkey_ptr int64, opt int32) int32 {
ctx := wasmer.IntoInstanceContext(context)
data := ctx.Data().(map[int]int)
memory := ctx.Memory()
signature := memory.Data()[sig_ptr : sig_ptr+70]
digest := memory.Data()[digest_ptr : digest_ptr+32]
pubkey := memory.Data()[pubkey_ptr : pubkey_ptr+int64(data[int(pubkey_ptr)])]
pemCert, _ := pem.Decode(pubkey)
var cert *x509.Certificate
cert, err := x509.ParseCertificate(pemCert.Bytes)
if err != nil {
return 0
}
pk := cert.PublicKey
r, s, err := unmarshalECDSASignature(signature)
if err != nil {
return 0
}
isValid := ecdsa.Verify(pk.(*ecdsa.PublicKey), digest, r, s)
if isValid {
return 1
} else {
return 0
}
}
func unmarshalECDSASignature(raw []byte) (*big.Int, *big.Int, error) {
sig := new(ECDSASignature)
_, err := asn1.Unmarshal(raw, sig)
if err != nil {
return nil, nil, fmt.Errorf("failed unmashalling signature [%s]", err)
}
// Validate sig
if sig.R == nil {
return nil, nil, fmt.Errorf("invalid signature, r must be different from nil")
}
if sig.S == nil {
return nil, nil, fmt.Errorf("invalid signature, s must be different from nil")
}
if sig.R.Sign() != 1 {
return nil, nil, fmt.Errorf("invalid signature, r must be larger than zero")
}
if sig.S.Sign() != 1 {
return nil, nil, fmt.Errorf("invalid signature, s must be larger than zero")
}
return sig.R, sig.S, nil
}
func (im *Imports) importECDSA() {
var err error
im.imports, err = im.imports.Append("ecdsa_verify", ecdsa_verify, C.ecdsa_verify)
if err != nil {
return
}
}
// Bytes returns a serialized, storable representation of this key
func (priv *PrivateKey) Bytes() ([]byte, error) {
if priv.K == nil {
return nil, fmt.Errorf("ECDSAPrivateKey.K is nil, please invoke FromBytes()")
}
r := make([]byte, 32)
a := priv.K.D.Bytes()
copy(r[32-len(a):], a)
return r, nil
}
func (pub *PublicKey) Bytes() ([]byte, error) {
x := pub.k.X.Bytes()
y := pub.k.Y.Bytes()
return bytes.Join(
[][]byte{
{0x04},
make([]byte, 32-len(x)), x, // padding to 32 bytes
make([]byte, 32-len(y)), y,
}, nil), nil
}
func UnmarshalPrivateKey(data []byte, opt AlgorithmOption) (crypto.PrivateKey, error) {
if len(data) == 0 {
return nil, fmt.Errorf("empty private key data")
}
key := &PrivateKey{K: new(ecdsa.PrivateKey)}
key.K.D = big.NewInt(0)
key.K.D.SetBytes(data)
switch opt {
case Secp256r1:
key.K.Curve = elliptic.P256()
default:
return nil, fmt.Errorf("unsupported algorithm option")
}
key.K.PublicKey.X, key.K.PublicKey.Y = key.K.Curve.ScalarBaseMult(data)
return key, nil
}
func UnmarshalPublicKey(data []byte, opt AlgorithmOption) (crypto.PublicKey, error) {
if len(data) == 0 {
return nil, fmt.Errorf("empty public key data")
}
key := &PublicKey{k: new(ecdsa.PublicKey)}
key.k.X = big.NewInt(0)
key.k.Y = big.NewInt(0)
if len(data) != 65 {
return nil, fmt.Errorf("public key data length is not 65")
}
key.k.X.SetBytes(data[1:33])
key.k.Y.SetBytes(data[33:])
switch opt {
case Secp256r1:
key.k.Curve = elliptic.P256()
}
return key, nil
}
package validatorlib
import (
"encoding/json"
"fmt"
"strings"
"github.com/gogo/protobuf/proto"
mb "github.com/hyperledger/fabric-protos-go/msp"
"github.com/hyperledger/fabric-protos-go/peer"
"github.com/hyperledger/fabric/bccsp/factory"
"github.com/hyperledger/fabric/common/cauthdsl"
"github.com/hyperledger/fabric/msp"
"github.com/hyperledger/fabric/protoutil"
"gitlab.33.cn/link33/sidecar/model/pb"
)
const (
FABRIC_EVALUATOR = "fabric_evaluator"
)
var evaluatorMap map[string]*PolicyEvaluator
type valiadationArtifacts struct {
rwset []byte
prp []byte
endorsements []*peer.Endorsement
cap *peer.ChaincodeActionPayload
payload payloadInfo
}
type ValidatorInfo struct {
ChainId string `json:"chain_id"`
ConfByte []string `json:"conf_byte"`
Policy string `json:"policy"`
Cid string `json:"cid"`
}
type payloadInfo struct {
Index int `json:"index"`
DstChainId string `json:"dst_chain_id"`
SrcContractId string `json:"src_contract_id"`
DstContractId string `json:"dst_contract_id"`
Func string `json:"func"`
Args string `json:args`
Callback string `json:callback`
}
func GetPolicyEnvelope(policy string) ([]byte, error) {
policyEnv, err := cauthdsl.FromString(policy)
if err != nil {
return nil, err
}
policyBytes, err := proto.Marshal(policyEnv)
if err != nil {
return nil, err
}
return policyBytes, nil
}
func UnmarshalValidatorInfo(validatorBytes []byte) (*ValidatorInfo, error) {
vInfo := &ValidatorInfo{}
if err := json.Unmarshal(validatorBytes, vInfo); err != nil {
return nil, err
}
return vInfo, nil
}
func ExtractValidationArtifacts(proof []byte) (*valiadationArtifacts, error) {
return extractValidationArtifacts(proof)
}
func extractValidationArtifacts(proof []byte) (*valiadationArtifacts, error) {
cap, err := protoutil.UnmarshalChaincodeActionPayload(proof)
if err != nil {
return nil, err
}
pRespPayload, err := protoutil.UnmarshalProposalResponsePayload(cap.Action.ProposalResponsePayload)
if err != nil {
err = fmt.Errorf("GetProposalResponsePayload error %s", err)
return nil, err
}
if pRespPayload.Extension == nil {
err = fmt.Errorf("nil pRespPayload.Extension")
return nil, err
}
respPayload, err := protoutil.UnmarshalChaincodeAction(pRespPayload.Extension)
if err != nil {
err = fmt.Errorf("GetChaincodeAction error %s", err)
return nil, err
}
var payloadArray []payloadInfo
err = json.Unmarshal(respPayload.Response.Payload, &payloadArray)
if err != nil {
return nil, err
}
return &valiadationArtifacts{
rwset: respPayload.Results,
prp: cap.Action.ProposalResponsePayload,
endorsements: cap.Action.Endorsements,
cap: cap,
payload: payloadArray[len(payloadArray)-1],
}, nil
}
func PreCheck(proof, payload []byte, cid string) (*valiadationArtifacts, error) {
// Get the validation artifacts that help validate the chaincodeID and policy
artifact, err := extractValidationArtifacts(proof)
if err != nil {
return nil, err
}
err = ValidateChainCodeID(artifact.prp, cid)
if err != nil {
return nil, err
}
err = ValidatePayload(artifact.payload, payload)
if err != nil {
return nil, err
}
return artifact, nil
}
func ValidateV14(proof, payload, policyBytes []byte, confByte []string, cid, from string) error {
// Get the validation artifacts that help validate the chaincodeID and policy
artifact, err := extractValidationArtifacts(proof)
if err != nil {
return err
}
err = ValidateChainCodeID(artifact.prp, cid)
if err != nil {
return err
}
err = ValidatePayload(artifact.payload, payload)
if err != nil {
return err
}
signatureSet := GetSignatureSet(artifact)
pe, err := NewPolicyEvaluator(confByte)
if err != nil {
return err
}
return pe.Evaluate(policyBytes, signatureSet)
}
func ValidateChainCodeID(prp []byte, name string) error {
payload, err := protoutil.UnmarshalProposalResponsePayload(prp)
if err != nil {
err = fmt.Errorf("GetProposalResponsePayload error %s", err)
return err
}
chaincodeAct, err := protoutil.UnmarshalChaincodeAction(payload.Extension)
if err != nil {
err = fmt.Errorf("GetChaincodeAction error %s", err)
return err
}
if name != chaincodeAct.ChaincodeId.Name {
return fmt.Errorf("chaincode id does not match")
}
return nil
}
func ValidatePayload(info payloadInfo, payloadByte []byte) error {
payload := &pb.Payload{}
if err := payload.Unmarshal(payloadByte); err != nil {
return err
}
if payload.Encrypted {
return nil
}
content := &pb.Content{}
if err := content.Unmarshal(payload.Content); err != nil {
return fmt.Errorf("unmarshal ibtp payload content: %w", err)
}
if info.DstContractId != content.DstContractId {
return fmt.Errorf("dst contrct id not correct")
}
if info.SrcContractId != content.SrcContractId {
return fmt.Errorf("src contrct id not correct")
}
if info.Callback != content.Callback {
return fmt.Errorf("callback not correct")
}
args := strings.Split(info.Args, ",")
for index, arg := range args {
if arg != string(content.Args[index]) {
return fmt.Errorf("args not correct")
}
}
return nil
}
type PolicyEvaluator struct {
msp.IdentityDeserializer
}
func NewPolicyEvaluator(confBytes []string) (*PolicyEvaluator, error) {
mspList := make([]msp.MSP, len(confBytes))
for i, confByte := range confBytes {
tempBccsp, err := msp.New(
&msp.BCCSPNewOpts{NewBaseOpts: msp.NewBaseOpts{Version: msp.MSPv1_3}},
factory.GetDefault(),
)
if err != nil {
return nil, err
}
conf := &mb.MSPConfig{}
if err := proto.UnmarshalText(confByte, conf); err != nil {
return nil, err
}
err = tempBccsp.Setup(conf)
if err != nil {
return nil, err
}
mspList[i] = tempBccsp
}
manager := msp.NewMSPManager()
err := manager.Setup(mspList)
if err != nil {
return nil, err
}
deserializer := &dynamicDeserializer{mspm: manager}
pe := &PolicyEvaluator{IdentityDeserializer: deserializer}
return pe, nil
}
func (id *PolicyEvaluator) Evaluate(policyBytes []byte, signatureSet []*protoutil.SignedData) error {
pp := cauthdsl.NewPolicyProvider(id.IdentityDeserializer)
policy, _, err := pp.NewPolicy(policyBytes)
if err != nil {
return err
}
return policy.EvaluateSignedData(signatureSet)
}
func GetSignatureSet(artifact *valiadationArtifacts) []*protoutil.SignedData {
signatureSet := []*protoutil.SignedData{}
for _, endorsement := range artifact.endorsements {
data := make([]byte, len(artifact.prp)+len(endorsement.Endorser))
copy(data, artifact.prp)
copy(data[len(artifact.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,
})
}
return signatureSet
}
type dynamicDeserializer struct {
mspm msp.MSPManager
}
func (ds *dynamicDeserializer) DeserializeIdentity(serializedIdentity []byte) (msp.Identity, error) {
return ds.mspm.DeserializeIdentity(serializedIdentity)
}
func (ds *dynamicDeserializer) IsWellFormed(identity *mb.SerializedIdentity) error {
return ds.mspm.IsWellFormed(identity)
}
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"
//export fabric_validate_v13
func fabric_validate_v13(context unsafe.Pointer, proof_ptr int64, validator_ptr int64) int32 {
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
}
}
{"Proposal":{"TxnID":"8d4a15dbcf8f5130331e06bf2eacdcb62375ce0f3b20fea3409b3d91e7695323","header":"CmgIAxoLCOOC4fQFEIjRwTkiCW15Y2hhbm5lbCpAOGQ0YTE1ZGJjZjhmNTEzMDMzMWUwNmJmMmVhY2RjYjYyMzc1Y2UwZjNiMjBmZWEzNDA5YjNkOTFlNzY5NTMyMzoKEggSBmJyb2tlchLTBgq2BgoHT3JnMk1TUBKqBi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQpNSUlDS1RDQ0FkQ2dBd0lCQWdJUkFLbEl1NkVxVGdJN3B1cGpVUGM3bGNFd0NnWUlLb1pJemowRUF3SXdjekVMCk1Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBZ1RDa05oYkdsbWIzSnVhV0V4RmpBVUJnTlZCQWNURFZOaGJpQkcKY21GdVkybHpZMjh4R1RBWEJnTlZCQW9URUc5eVp6SXVaWGhoYlhCc1pTNWpiMjB4SERBYUJnTlZCQU1URTJOaApMbTl5WnpJdVpYaGhiWEJzWlM1amIyMHdIaGNOTWpBd05ERTJNRE15TkRBd1doY05NekF3TkRFME1ETXlOREF3CldqQnJNUXN3Q1FZRFZRUUdFd0pWVXpFVE1CRUdBMVVFQ0JNS1EyRnNhV1p2Y201cFlURVdNQlFHQTFVRUJ4TU4KVTJGdUlFWnlZVzVqYVhOamJ6RU9NQXdHQTFVRUN4TUZZV1J0YVc0eEh6QWRCZ05WQkFNTUZrRmtiV2x1UUc5eQpaekl1WlhoaGJYQnNaUzVqYjIwd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFRUFRyZ0g0NU4vCnBxL0NCZXl3WFFIZk0zeDdLc0hnUUd3bDBHSzZxR0dReFpUTW5MZ3J1QWpoSURwWXViVitlODVQSEEwbm03dTcKOVo1UUsyTFFEc3p5bzAwd1N6QU9CZ05WSFE4QkFmOEVCQU1DQjRBd0RBWURWUjBUQVFIL0JBSXdBREFyQmdOVgpIU01FSkRBaWdDQXBIWGtscFEva205TVpPdHBCek5aaTN2R1MxNDl2Y3NGbERMdDkrbkc0T1RBS0JnZ3Foa2pPClBRUURBZ05IQURCRUFpQVowZXMwQUNhSDVyV2E2MFJONlFJTDZOZ2NTTGFmNFhMblpqZDh1czVISVFJZ0xWMk0KM08wdmMwREF4QldmN3VBSjBXU0xyR3hMMVBEa3hXLy9Kd2UzWWdVPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tChIYCPnx6/3GjKjk3FMlOKUaQnbAuYjit5z9","payload":"CkIKQAgBEggSBmJyb2tlchoyCg1pbnRlcmNoYWluR2V0CgIxMgoBMQoUY2hhbm5lbCZkYXRhX3N3YXBwZXIKBHBhdGg="},"Responses":[{"Endorser":"localhost:10051","Status":200,"ChaincodeStatus":200,"version":1,"response":{"status":200,"payload":"eyJvayI6ZmFsc2UsIm1lc3NhZ2UiOiJpbmNvcnJlY3QgaW5kZXgsIGV4cGVjdCAyIiwiZGF0YSI6bnVsbH0="},"payload":"CiA9aI7qyaL5DGtSjUCojZbtl75jes5EeoGHauROvrYCRBKeAQpJEi8KBmJyb2tlchIlChAKCmFkbWluLWxpc3QSAggDChEKCmlubmVyLW1ldGESAwiGBRIWCgRsc2NjEg4KDAoGYnJva2VyEgIIAxpDCMgBGj57Im9rIjpmYWxzZSwibWVzc2FnZSI6ImluY29ycmVjdCBpbmRleCwgZXhwZWN0IDIiLCJkYXRhIjpudWxsfSIMEgZicm9rZXIaAnYw","endorsement":{"endorser":"CgdPcmcyTVNQEqoGLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNLRENDQWM2Z0F3SUJBZ0lRY0pncURPNWJ0WFBHRUdxZ3hMVGF2ekFLQmdncWhrak9QUVFEQWpCek1Rc3cKQ1FZRFZRUUdFd0pWVXpFVE1CRUdBMVVFQ0JNS1EyRnNhV1p2Y201cFlURVdNQlFHQTFVRUJ4TU5VMkZ1SUVaeQpZVzVqYVhOamJ6RVpNQmNHQTFVRUNoTVFiM0puTWk1bGVHRnRjR3hsTG1OdmJURWNNQm9HQTFVRUF4TVRZMkV1CmIzSm5NaTVsZUdGdGNHeGxMbU52YlRBZUZ3MHlNREEwTVRZd016STBNREJhRncwek1EQTBNVFF3TXpJME1EQmEKTUdveEN6QUpCZ05WQkFZVEFsVlRNUk13RVFZRFZRUUlFd3BEWVd4cFptOXlibWxoTVJZd0ZBWURWUVFIRXcxVApZVzRnUm5KaGJtTnBjMk52TVEwd0N3WURWUVFMRXdSd1pXVnlNUjh3SFFZRFZRUURFeFp3WldWeU1TNXZjbWN5CkxtVjRZVzF3YkdVdVkyOXRNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUU4cTZWZnArRkNNVm8KZFl2anUyUnpwUnJHb2N3QTdrYmd5SmtHOW1hS2h0UXhyRHlqQi9QY2liVExhZm10NXMraGt5MVAzVmlMQ2tObQpLMnVuMmtXOEY2Tk5NRXN3RGdZRFZSMFBBUUgvQkFRREFnZUFNQXdHQTFVZEV3RUIvd1FDTUFBd0t3WURWUjBqCkJDUXdJb0FnS1IxNUphVVA1SnZUR1RyYVFjeldZdDd4a3RlUGIzTEJaUXk3ZmZweHVEa3dDZ1lJS29aSXpqMEUKQXdJRFNBQXdSUUloQVB2b0dZU1I5amE4QlUrYmcvb0g1MEptL2NGbGhqdzhQYjdQRS9yU1MyeUFBaUFHLzZhRQpkWkNpQjlSRmprVklqZEVLQURFUUIvcmtaWnU3Q29lODFtOStUQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K","signature":"MEUCIQDidRlKTnmFAqNYlkjTMAAwiDYD2XInPoZSWfUBf46a2gIgfHbPWHqkwFhRoSoRLuSGa0d0Yb8LgXpZ6hQhvcFSs0s="}}],"TransactionID":"8d4a15dbcf8f5130331e06bf2eacdcb62375ce0f3b20fea3409b3d91e7695323","TxValidationCode":0,"ChaincodeStatus":200,"Payload":"eyJvayI6ZmFsc2UsIm1lc3NhZ2UiOiJpbmNvcnJlY3QgaW5kZXgsIGV4cGVjdCAyIiwiZGF0YSI6bnVsbH0="}
\ No newline at end of file
package validatorlib
import (
"github.com/wasmerio/go-ext-wasm/wasmer"
)
type Imports struct {
imports *wasmer.Imports
}
func New() (*wasmer.Imports, error) {
imports := &Imports{
imports: wasmer.NewImports(),
}
imports.importECDSA()
imports.importFabricV14()
imports.importFabricV13()
return imports.imports, nil
}
package validator
import (
"encoding/json"
"fmt"
"strconv"
"sync"
"github.com/gogo/protobuf/proto"
"github.com/meshplus/bitxhub-kit/types"
"github.com/sirupsen/logrus"
"gitlab.33.cn/link33/sidecar/model/pb"
"gitlab.33.cn/link33/sidecar/pkg/validator/validatorlib"
"gitlab.33.cn/link33/sidecar/pkg/wasm"
)
// Validator is the instance that can use wasm to verify transaction validity
type WasmValidator struct {
wasm *wasm.Wasm
input []byte
ledger Ledger
logger logrus.FieldLogger
instances *sync.Map
}
// New a validator instance
func NewWasmValidator(ledger Ledger, logger logrus.FieldLogger, instances *sync.Map) *WasmValidator {
return &WasmValidator{
ledger: ledger,
logger: logger,
instances: instances,
}
}
// Verify will check whether the transaction info is valid
func (vlt *WasmValidator) Verify(address, from string, proof, payload []byte, validators string) (bool, error) {
ruleHash, err := vlt.initRule(address, from, proof, payload, validators)
if err != nil {
return false, err
}
ret, err := vlt.wasm.Execute(vlt.input)
if err != nil {
return false, err
}
// put wasm instance into pool
v, ok := vlt.instances.Load(ruleHash)
if !ok {
return false, fmt.Errorf("load wasm instance failed")
}
v.(*sync.Pool).Put(vlt.wasm.Instance)
// check execution status
result, err := strconv.Atoi(string(ret))
if err != nil {
return false, err
}
if result == 0 {
return false, nil
}
return true, nil
}
// InitRule can import a specific rule for validator to verify the transaction
func (vlt *WasmValidator) initRule(address, from string, proof, payload []byte, validators string) (string, error) {
err := vlt.setTransaction(address, from, proof, validators, payload)
if err != nil {
return "", err
}
imports, err := validatorlib.New()
if err != nil {
return "", err
}
contractByte := vlt.ledger.GetCode(types.NewAddressByStr(address))
if contractByte == nil {
return "", fmt.Errorf("this rule address does not exist")
}
wasmInstance, err := wasm.New(contractByte, imports, vlt.instances)
if err != nil {
return "", err
}
vlt.wasm = wasmInstance
contract := &wasm.Contract{}
if err := json.Unmarshal(contractByte, contract); err != nil {
return "", fmt.Errorf("contract byte not correct")
}
return contract.Hash.String(), nil
}
func (vlt *WasmValidator) setTransaction(address, from string, proof []byte, validators string, payload []byte) error {
invokePayload := &pb.InvokePayload{
Method: "start_verify",
Args: []*pb.Arg{
{Type: pb.Arg_Bytes, Value: proof},
{Type: pb.Arg_Bytes, Value: []byte(validators)},
{Type: pb.Arg_Bytes, Value: payload},
},
}
input, _ := proto.Marshal(invokePayload)
vlt.input = input
return nil
}
package validator
import (
"encoding/json"
"fmt"
"io/ioutil"
"strconv"
"sync"
"testing"
"github.com/stretchr/testify/require"
"gitlab.33.cn/link33/sidecar/model/pb"
"gitlab.33.cn/link33/sidecar/pkg/validator/validatorlib"
"gitlab.33.cn/link33/sidecar/pkg/wasm"
)
func TestWasmValidator(t *testing.T) {
wasmBytes, err := ioutil.ReadFile("./testdata/hpc_demo.wasm")
require.Nil(t, err)
proof, err := ioutil.ReadFile("./testdata/proof_1.0.0_rc")
require.Nil(t, err)
validators, err := ioutil.ReadFile("./testdata/validator_1.0.0_rc")
require.Nil(t, err)
content := &pb.Content{
SrcContractId: "mychannel&transfer",
DstContractId: "mychannel&transfer",
Func: "interchainCharge",
Args: [][]byte{[]byte("Alice"), []byte("Alice"), []byte("1")},
Callback: "interchainConfirm",
}
bytes, err := content.Marshal()
require.Nil(t, err)
payload := &pb.Payload{
Encrypted: false,
Content: bytes,
}
body, err := payload.Marshal()
require.Nil(t, err)
validator := &WasmValidator{
instances: &sync.Map{},
}
wasmCode := &wasm.Contract{
Code: wasmBytes,
}
contractBytes, err := json.Marshal(wasmCode)
require.Nil(t, err)
imports, err := validatorlib.New()
require.Nil(t, err)
wasm, err := wasm.New(contractBytes, imports, validator.instances)
require.Nil(t, err)
validator.wasm = wasm
err = validator.setTransaction("", "0xe02d8fdacd59020d7f292ab3278d13674f5c404d", proof, string(validators), body)
require.Nil(t, err)
ret, err := validator.wasm.Execute(validator.input)
require.Nil(t, err)
result, err := strconv.Atoi(string(ret))
require.Nil(t, err)
fmt.Println(result)
}
func BenchmarkHpcWasm_Verify(b *testing.B) {
wasmBytes, err := ioutil.ReadFile("./testdata/hpc_demo.wasm")
require.Nil(b, err)
// proof, err := ioutil.ReadFile("./testdata/proof_1.0.0_rc")
// require.Nil(b, err)
// validators, err := ioutil.ReadFile("./testdata/validator_1.0.0_rc")
// require.Nil(b, err)
content := &pb.Content{
SrcContractId: "mychannel&transfer",
DstContractId: "mychannel&transfer",
Func: "interchainCharge",
Args: [][]byte{[]byte("Alice"), []byte("Alice"), []byte("1")},
Callback: "interchainConfirm",
}
bytes, err := content.Marshal()
require.Nil(b, err)
payload := &pb.Payload{
Encrypted: false,
Content: bytes,
}
body, err := payload.Marshal()
require.Nil(b, err)
validator := &WasmValidator{
instances: &sync.Map{},
}
wasmCode := &wasm.Contract{
Code: wasmBytes,
}
contractBytes, err := json.Marshal(wasmCode)
require.Nil(b, err)
imports, err := validatorlib.New()
require.Nil(b, err)
wasm, err := wasm.New(contractBytes, imports, validator.instances)
require.Nil(b, err)
validator.wasm = wasm
err = validator.setTransaction("", "0xe02d8fdacd59020d7f292ab3278d13674f5c404d", []byte("111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"), "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", body)
require.Nil(b, err)
// for i := 0; i < 400000; i++ {
// _, err := validator.wasm.Execute(validator.input)
// require.Nil(b, err)
// }
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := validator.wasm.Execute(validator.input)
require.Nil(b, err)
}
}
package wasm
import (
"fmt"
)
// SetString set the string type arg for wasm
func (w *Wasm) SetString(str string) (int32, error) {
alloc := w.Instance.Exports["allocate"]
if alloc == nil {
return 0, fmt.Errorf("not found allocate method")
}
lengthOfStr := len(str)
allocResult, err := alloc(lengthOfStr)
if err != nil {
return 0, err
}
inputPointer := allocResult.ToI32()
memory := w.Instance.Memory.Data()[inputPointer:]
var i int
for i = 0; i < lengthOfStr; i++ {
memory[i] = str[i]
}
memory[i] = 0
w.argMap[int(inputPointer)] = len(str)
return inputPointer, nil
}
// SetBytes set bytes type arg for wasm
func (w *Wasm) SetBytes(b []byte) (int32, error) {
alloc := w.Instance.Exports["allocate"]
if alloc == nil {
return 0, fmt.Errorf("not found allocate method")
}
lengthOfBytes := len(b)
allocResult, err := alloc(lengthOfBytes)
if err != nil {
return 0, err
}
inputPointer := allocResult.ToI32()
memory := w.Instance.Memory.Data()[inputPointer:]
var i int
for i = 0; i < lengthOfBytes; i++ {
memory[i] = b[i]
}
memory[i] = 0
w.argMap[int(inputPointer)] = len(b)
return inputPointer, nil
}
// FreeString free the string type arg for wasm
func (w *Wasm) FreeString(inputPointer interface{}, str string) error {
dealloc := w.Instance.Exports["deallocate"]
if dealloc == nil {
return fmt.Errorf("not found allocate method")
}
lengthOfStr := len(str)
_, err := dealloc(inputPointer, lengthOfStr)
if err != nil {
return err
}
delete(w.argMap, int(inputPointer.(int32)))
return nil
}
// FreeBytes free the bytes type arg for wasm
func (w *Wasm) FreeBytes(inputPointer interface{}, b []byte) error {
dealloc := w.Instance.Exports["deallocate"]
if dealloc == nil {
return fmt.Errorf("not found allocate method")
}
lengthOfBytes := len(b)
_, err := dealloc(inputPointer, lengthOfBytes)
if err != nil {
return err
}
delete(w.argMap, int(inputPointer.(int32)))
return nil
}
package wasm
import (
"encoding/json"
"fmt"
"strconv"
"sync"
"github.com/gogo/protobuf/proto"
"github.com/meshplus/bitxhub-kit/types"
"github.com/wasmerio/go-ext-wasm/wasmer"
"gitlab.33.cn/link33/sidecar/model/pb"
)
const (
CONTEXT_ARGMAP = "argmap"
CONTEXT_INTERFACE = "interface"
ACCOUNT = "account"
ALLOC_MEM = "allocate"
)
var errorLackOfMethod = fmt.Errorf("wasm execute: lack of method name")
func getInstance(contract *Contract, imports *wasmer.Imports, instances *sync.Map) (wasmer.Instance, error) {
var (
instance wasmer.Instance
err error
pool *sync.Pool
)
v, ok := instances.Load(contract.Hash.String())
if !ok {
v = &sync.Pool{
New: func() interface{} {
instance, _ := wasmer.NewInstanceWithImports(contract.Code, imports)
return instance
},
}
instances.Store(contract.Hash.String(), v)
}
pool = v.(*sync.Pool)
rawInstance := pool.Get()
if rawInstance == nil {
instance, err = wasmer.NewInstanceWithImports(contract.Code, imports)
if err != nil {
return wasmer.Instance{}, err
}
} else {
instance = rawInstance.(wasmer.Instance)
}
return instance, nil
}
// Wasm represents the wasm vm in BitXHub
type Wasm struct {
// wasm instance
Instance wasmer.Instance
context map[string]interface{}
argMap map[int]int
sync.RWMutex
}
// Contract represents the smart contract structure used in the wasm vm
type Contract struct {
// contract byte
Code []byte
// contract hash
Hash *types.Hash
}
// New creates a wasm vm instance
func New(contractByte []byte, imports *wasmer.Imports, instances *sync.Map) (*Wasm, error) {
wasm := &Wasm{}
contract := &Contract{}
if err := json.Unmarshal(contractByte, contract); err != nil {
return wasm, fmt.Errorf("contract byte not correct")
}
if len(contract.Code) == 0 {
return wasm, fmt.Errorf("contract byte is empty")
}
instance, err := getInstance(contract, imports, instances)
if err != nil {
return nil, err
}
wasm.Instance = instance
wasm.argMap = make(map[int]int)
wasm.context = make(map[string]interface{})
return wasm, nil
}
func EmptyImports() (*wasmer.Imports, error) {
return wasmer.NewImports(), nil
}
func (w *Wasm) Execute(input []byte) ([]byte, error) {
payload := &pb.InvokePayload{}
if err := proto.Unmarshal(input, payload); err != nil {
return nil, err
}
if payload.Method == "" {
return nil, errorLackOfMethod
}
alloc := w.Instance.Exports[ALLOC_MEM]
if alloc == nil {
return nil, fmt.Errorf("not found allocate method")
}
w.context[ALLOC_MEM] = alloc
methodName, ok := w.Instance.Exports[payload.Method]
if !ok {
return nil, fmt.Errorf("wrong rule contract")
}
slice := make([]interface{}, len(payload.Args))
for i := range slice {
arg := payload.Args[i]
switch arg.Type {
case pb.Arg_I32:
temp, err := strconv.Atoi(string(arg.Value))
if err != nil {
return nil, err
}
slice[i] = temp
case pb.Arg_I64:
temp, err := strconv.ParseInt(string(arg.Value), 10, 64)
if err != nil {
return nil, err
}
slice[i] = temp
case pb.Arg_F32:
temp, err := strconv.ParseFloat(string(arg.Value), 32)
if err != nil {
return nil, err
}
slice[i] = temp
case pb.Arg_F64:
temp, err := strconv.ParseFloat(string(arg.Value), 64)
if err != nil {
return nil, err
}
slice[i] = temp
case pb.Arg_String:
inputPointer, err := w.SetString(string(arg.Value))
if err != nil {
return nil, err
}
slice[i] = inputPointer
case pb.Arg_Bytes:
inputPointer, err := w.SetBytes(arg.Value)
if err != nil {
return nil, err
}
slice[i] = inputPointer
case pb.Arg_Bool:
inputPointer, err := strconv.Atoi(string(arg.Value))
if err != nil {
return nil, err
}
slice[i] = inputPointer
default:
return nil, fmt.Errorf("input type not support")
}
}
w.context[CONTEXT_ARGMAP] = w.argMap
w.Instance.SetContextData(w.context)
result, err := methodName(slice...)
if err != nil {
return nil, err
}
for i := range slice {
arg := payload.Args[i]
switch arg.Type {
case pb.Arg_String:
if err := w.FreeString(slice[i], string(arg.Value)); err != nil {
return nil, err
}
case pb.Arg_Bytes:
if err := w.FreeBytes(slice[i], arg.Value); err != nil {
return nil, err
}
}
}
return []byte(result.String()), err
}
func (w *Wasm) SetContext(key string, value interface{}) {
w.Lock()
defer w.Unlock()
w.context[key] = value
}
func (w *Wasm) GetContext(key string) interface{} {
w.Lock()
defer w.Unlock()
return w.context[key]
}
package wasm
import (
"encoding/json"
"fmt"
"io/ioutil"
"sync"
"testing"
"github.com/meshplus/bitxhub-kit/types"
"github.com/stretchr/testify/assert"
"github.com/wasmerio/go-ext-wasm/wasmer"
"gitlab.33.cn/link33/sidecar/model/pb"
"gitlab.33.cn/link33/sidecar/pkg/wasm/wasmlib"
)
func TestExecute(t *testing.T) {
data, err := ioutil.ReadFile("./testdata/wasm_test.wasm")
assert.Nil(t, err)
contract := &Contract{
Code: data,
Hash: &types.Hash{},
}
bytes, err := json.Marshal(contract)
assert.Nil(t, err)
imports := wasmer.NewImports()
instances := &sync.Map{}
wasm, err := New(bytes, imports, instances)
assert.Nil(t, err)
input := &pb.InvokePayload{
Method: "a",
Args: []*pb.Arg{
{Type: pb.Arg_I32, Value: []byte(fmt.Sprintf("%d", 1))},
{Type: pb.Arg_I32, Value: []byte(fmt.Sprintf("%d", 2))},
},
}
inputBytes, err := input.Marshal()
assert.Nil(t, err)
ret, err := wasm.Execute(inputBytes)
assert.Nil(t, err)
fmt.Println(string(ret))
}
func TestImportExecute(t *testing.T) {
data, err := ioutil.ReadFile("./testdata/test_demo.wasm")
assert.Nil(t, err)
hello := "hello world"
contract := &Contract{
Code: data,
Hash: &types.Hash{},
}
bytes, err := json.Marshal(contract)
assert.Nil(t, err)
imports, err := wasmlib.New()
assert.Nil(t, err)
instances := &sync.Map{}
wasm, err := New(bytes, imports, instances)
assert.Nil(t, err)
input := &pb.InvokePayload{
Method: "start_verify",
Args: []*pb.Arg{
{Type: pb.Arg_Bytes, Value: []byte(fmt.Sprintf("%d", 1))},
{Type: pb.Arg_Bytes, Value: []byte(fmt.Sprintf("%d", 2))},
{Type: pb.Arg_Bytes, Value: []byte(fmt.Sprintf("%d", 2))},
},
}
inputBytes, err := input.Marshal()
assert.Nil(t, err)
wasm.SetContext("hello", hello)
ret, err := wasm.Execute(inputBytes)
assert.Nil(t, err)
fmt.Println(string(ret))
}
func BenchmarkImportExecute(b *testing.B) {
data, err := ioutil.ReadFile("./testdata/test_demo.wasm")
assert.Nil(b, err)
hello := "hello world"
contract := &Contract{
Code: data,
Hash: &types.Hash{},
}
bytes, err := json.Marshal(contract)
assert.Nil(b, err)
imports, err := wasmlib.New()
assert.Nil(b, err)
instances := &sync.Map{}
wasm, err := New(bytes, imports, instances)
assert.Nil(b, err)
input := &pb.InvokePayload{
Method: "start_verify",
Args: []*pb.Arg{
{Type: pb.Arg_Bytes, Value: []byte("1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")},
{Type: pb.Arg_Bytes, Value: []byte("1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")},
{Type: pb.Arg_Bytes, Value: []byte(fmt.Sprintf("%d", 2))},
},
}
inputBytes, err := input.Marshal()
assert.Nil(b, err)
wasm.SetContext("hello", hello)
for i := 0; i < 200000; i++ {
_, err := wasm.Execute(inputBytes)
assert.Nil(b, err)
// fmt.Println(string(ret))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := wasm.Execute(inputBytes)
assert.Nil(b, err)
// fmt.Println(string(ret))
}
}
package wasmlib
import (
"github.com/wasmerio/go-ext-wasm/wasmer"
)
type Imports struct {
imports *wasmer.Imports
}
func New() (*wasmer.Imports, error) {
imports := &Imports{
imports: wasmer.NewImports(),
}
imports.importWasmLib()
return imports.imports, nil
}
package wasmlib
// #include <stdlib.h>
//
// extern int32_t test_verify(void *context, long long proof_ptr, long long validator_ptr, long long payload_ptr);
import "C"
import (
"unsafe"
"github.com/wasmerio/go-ext-wasm/wasmer"
)
//export test_verify
func test_verify(context unsafe.Pointer, proof_ptr int64, validator_ptr int64, payload_ptr int64) int32 {
ctx := wasmer.IntoInstanceContext(context)
ctxMap := ctx.Data().(map[string]interface{})
_ = ctxMap["argmap"].(map[int]int)
_ = 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)])]
// payload := memory.Data()[payload_ptr : payload_ptr+int64(data[int(payload_ptr)])]
// fmt.Println(proof)
// fmt.Println(validator)
// fmt.Println(payload)
// fmt.Println(ctxMap["hello"].(string))
return 1
}
func (im *Imports) importWasmLib() {
var err error
im.imports, err = im.imports.Append("test_verify", test_verify, C.test_verify)
if err != nil {
return
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment