Commit f3a87a2f authored by kingwang's avatar kingwang Committed by vipwzw

update 01/22

parent 60b1ada1
......@@ -9,6 +9,7 @@ import (
"github.com/33cn/chain33/client"
"github.com/33cn/chain33/queue"
"github.com/33cn/chain33/rpc/grpcclient"
"github.com/33cn/chain33/types"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
......@@ -93,7 +94,7 @@ func newParaChainAPI(api client.QueueProtocolAPI, grpcaddr string) ExecutorAPI {
if paraRemoteGrpcClient == "" {
paraRemoteGrpcClient = "127.0.0.1:8002"
}
conn, err := grpc.Dial(paraRemoteGrpcClient, grpc.WithInsecure())
conn, err := grpc.Dial(grpcclient.NewMultipleURL(paraRemoteGrpcClient), grpc.WithInsecure())
if err != nil {
panic(err)
}
......
......@@ -29,8 +29,10 @@ func TestGetRealTime(t *testing.T) {
if nettime.IsZero() {
return
}
//nettime 获取和本地时间应该
local := time.Now()
t.Log(nettime.Sub(local))
assert.Equal(t, int(local.Sub(nettime)/time.Second), 0)
nettime2 := GetRealTimeRetry(hosts, 10)
//get nettime error, ignore
if nettime2.IsZero() {
return
}
assert.Equal(t, int(nettime2.Sub(nettime)/time.Second), 0)
}
package grpcclient_test
import (
"context"
"testing"
"time"
"github.com/33cn/chain33/client/mocks"
qmocks "github.com/33cn/chain33/queue/mocks"
"github.com/33cn/chain33/rpc"
"github.com/33cn/chain33/rpc/grpcclient"
"github.com/33cn/chain33/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"google.golang.org/grpc"
)
func TestMultipleGRPC(t *testing.T) {
qapi := new(mocks.QueueProtocolAPI)
qapi.On("Query", "ticket", "RandNumHash", mock.Anything).Return(&types.ReplyHash{Hash: []byte("hello")}, nil)
//testnode setup
rpcCfg := new(types.RPC)
rpcCfg.GrpcBindAddr = "127.0.0.1:8003"
rpcCfg.JrpcBindAddr = "127.0.0.1:8004"
rpcCfg.MainnetJrpcAddr = rpcCfg.JrpcBindAddr
rpcCfg.Whitelist = []string{"127.0.0.1", "0.0.0.0"}
rpcCfg.JrpcFuncWhitelist = []string{"*"}
rpcCfg.GrpcFuncWhitelist = []string{"*"}
rpc.InitCfg(rpcCfg)
server := rpc.NewGRpcServer(&qmocks.Client{}, qapi)
assert.NotNil(t, server)
go server.Listen()
time.Sleep(time.Second)
//一个IP 有效,一个IP 无效
paraRemoteGrpcClient := "127.0.0.1:8004,127.0.0.1:8003,127.0.0.1"
conn, err := grpc.Dial(grpcclient.NewMultipleURL(paraRemoteGrpcClient), grpc.WithInsecure())
assert.Nil(t, err)
grpcClient := types.NewChain33Client(conn)
param := &types.ReqRandHash{
ExecName: "ticket",
BlockNum: 5,
Hash: []byte("hello"),
}
reply, err := grpcClient.QueryRandNum(context.Background(), param)
assert.Nil(t, err)
assert.Equal(t, reply.Hash, []byte("hello"))
}
package grpcclient
import (
"errors"
"fmt"
"net"
"strings"
"google.golang.org/grpc/resolver"
)
// Scheme 自定义grpc负载局衡名
const scheme = "multiple"
// Separator url分隔符
const separator = ":///"
// MultiPleHostsBalancerPrefix url前缀
const multiPleHostsBalancerPrefix = scheme + separator
// defaultGrpcPort 默认grpc端口
const defaultGrpcPort = "8802"
func parseTarget(target, defaultPort string) (host, port string, err error) {
if target == "" {
return "", "", errors.New("multiple resolver: missing address")
}
if ip := net.ParseIP(target); ip != nil {
return target, defaultPort, nil
}
if host, port, err = net.SplitHostPort(target); err == nil {
if port == "" {
return "", "", errors.New("multiple resolver: missing port after port-separator colon")
}
if host == "" {
host = "localhost"
}
return host, port, nil
}
if host, port, err = net.SplitHostPort(target + ":" + defaultPort); err == nil {
return host, port, nil
}
return "", "", fmt.Errorf("invalid target address %v, error info: %v", target, err)
}
type multipleBuilder struct{}
func (*multipleBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOption) (resolver.Resolver, error) {
r := &multipleResolver{
target: target,
cc: cc,
}
urls := strings.Split(target.Endpoint, ",")
if len(urls) < 1 {
return nil, fmt.Errorf("invalid target address %v", target)
}
for _, url := range urls {
host, port, err := parseTarget(url, defaultGrpcPort)
if err != nil {
return nil, err
}
if net.ParseIP(host) != nil {
r.addrs = append(r.addrs, resolver.Address{Addr: host + ":" + port})
}
}
r.start()
return r, nil
}
func (*multipleBuilder) Scheme() string {
return scheme
}
type multipleResolver struct {
target resolver.Target
cc resolver.ClientConn
addrs []resolver.Address
}
func (r *multipleResolver) start() {
r.cc.NewAddress(r.addrs)
}
func (*multipleResolver) ResolveNow(o resolver.ResolveNowOption) {}
func (*multipleResolver) Close() {}
func init() {
resolver.Register(&multipleBuilder{})
}
//NewMultipleURL 创建url
func NewMultipleURL(url string) string {
return multiPleHostsBalancerPrefix + url
}
......@@ -12,6 +12,7 @@ import (
"github.com/33cn/chain33/client"
"github.com/33cn/chain33/pluginmgr"
"github.com/33cn/chain33/queue"
_ "github.com/33cn/chain33/rpc/grpcclient" // register grpc multiple resolver
"github.com/33cn/chain33/types"
"golang.org/x/net/context"
"google.golang.org/grpc"
......@@ -197,6 +198,9 @@ func InitCfg(cfg *types.RPC) {
// New produce a rpc by cfg
func New(cfg *types.RPC) *RPC {
InitCfg(cfg)
if cfg.EnableTrace {
grpc.EnableTracing = true
}
return &RPC{cfg: cfg}
}
......
......@@ -103,7 +103,7 @@ func DecodeTx(tx *types.Transaction) (*Transaction, error) {
}
var pljson json.RawMessage
if pl != nil {
pljson, _ = types.PBToJSON(pl)
pljson, _ = types.PBToJSONUTF8(pl)
}
result := &Transaction{
Execer: string(tx.Execer),
......
......@@ -11,18 +11,12 @@ import (
"io"
"os"
"strings"
"time"
"github.com/33cn/chain33/rpc/jsonclient"
commandtypes "github.com/33cn/chain33/system/dapp/commands/types"
"github.com/33cn/chain33/types"
"github.com/spf13/cobra"
)
const (
defaultPrivacyMixCount = 16
)
// BTYCmd bty command
func BTYCmd() *cobra.Command {
cmd := &cobra.Command{
......@@ -35,9 +29,6 @@ func BTYCmd() *cobra.Command {
CreateRawWithdrawCmd(),
CreateRawSendToExecCmd(),
CreateTxGroupCmd(),
CreatePub2PrivTxCmd(),
CreatePriv2PrivTxCmd(),
CreatePriv2PubTxCmd(),
)
return cmd
}
......@@ -54,9 +45,6 @@ func CoinsCmd() *cobra.Command {
CreateRawWithdrawCmd(),
CreateRawSendToExecCmd(),
CreateTxGroupCmd(),
CreatePub2PrivTxCmd(),
CreatePriv2PrivTxCmd(),
CreatePriv2PubTxCmd(),
)
return cmd
}
......@@ -321,184 +309,3 @@ func createTxGroup(cmd *cobra.Command, args []string) {
grouptx := hex.EncodeToString(types.Encode(newtx))
fmt.Println(grouptx)
}
// CreatePub2PrivTxCmd create a public to privacy transaction
func CreatePub2PrivTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "pub2priv",
Short: "Create a public to privacy transaction",
Run: createPub2PrivTx,
}
createPub2PrivTxFlags(cmd)
return cmd
}
func createPub2PrivTxFlags(cmd *cobra.Command) {
cmd.Flags().StringP("pubkeypair", "p", "", "public key pair")
cmd.MarkFlagRequired("pubkeypair")
cmd.Flags().Float64P("amount", "a", 0.0, "transfer amount, at most 4 decimal places")
cmd.MarkFlagRequired("amount")
cmd.Flags().StringP("tokenname", "", "BTY", "token name")
cmd.Flags().StringP("note", "n", "", "note for transaction")
cmd.Flags().Int64P("expire", "", 0, "transfer expire, default one hour")
cmd.Flags().IntP("expiretype", "", 1, "0: height 1: time default is 1")
}
func createPub2PrivTx(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
pubkeypair, _ := cmd.Flags().GetString("pubkeypair")
amount := commandtypes.GetAmountValue(cmd, "amount")
tokenname, _ := cmd.Flags().GetString("tokenname")
note, _ := cmd.Flags().GetString("note")
expire, _ := cmd.Flags().GetInt64("expire")
expiretype, _ := cmd.Flags().GetInt("expiretype")
if expiretype == 0 {
if expire <= 0 {
fmt.Println("Invalid expire. expire must large than 0 in expiretype==0, expire", expire)
return
}
} else if expiretype == 1 {
if expire <= 0 {
expire = int64(time.Hour / time.Second)
}
} else {
fmt.Println("Invalid expiretype", expiretype)
return
}
params := types.ReqCreateTransaction{
Tokenname: tokenname,
Type: types.PrivacyTypePublic2Privacy,
Amount: amount,
Note: note,
Pubkeypair: pubkeypair,
Expire: expire,
}
ctx := jsonclient.NewRPCCtx(rpcLaddr, "privacy.CreateRawTransaction", params, nil)
ctx.RunWithoutMarshal()
}
// CreatePriv2PrivTxCmd create a privacy to privacy transaction
func CreatePriv2PrivTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "priv2priv",
Short: "Create a privacy to privacy transaction",
Run: createPriv2PrivTx,
}
createPriv2PrivTxFlags(cmd)
return cmd
}
func createPriv2PrivTxFlags(cmd *cobra.Command) {
cmd.Flags().StringP("pubkeypair", "p", "", "public key pair")
cmd.MarkFlagRequired("pubkeypair")
cmd.Flags().Float64P("amount", "a", 0.0, "transfer amount, at most 4 decimal places")
cmd.MarkFlagRequired("amount")
cmd.Flags().StringP("sender", "s", "", "account address")
cmd.MarkFlagRequired("sender")
cmd.Flags().StringP("tokenname", "t", "BTY", "token name")
cmd.Flags().StringP("note", "n", "", "note for transaction")
cmd.Flags().Int64P("expire", "", 0, "transfer expire, default one hour")
cmd.Flags().IntP("expiretype", "", 1, "0: height 1: time default is 1")
}
func createPriv2PrivTx(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
pubkeypair, _ := cmd.Flags().GetString("pubkeypair")
amount := commandtypes.GetAmountValue(cmd, "amount")
tokenname, _ := cmd.Flags().GetString("tokenname")
note, _ := cmd.Flags().GetString("note")
sender, _ := cmd.Flags().GetString("sender")
expire, _ := cmd.Flags().GetInt64("expire")
expiretype, _ := cmd.Flags().GetInt("expiretype")
if expiretype == 0 {
if expire <= 0 {
fmt.Println("Invalid expire. expire must large than 0 in expiretype==0, expire", expire)
return
}
} else if expiretype == 1 {
if expire <= 0 {
expire = int64(time.Hour / time.Second)
}
} else {
fmt.Println("Invalid expiretype", expiretype)
return
}
params := types.ReqCreateTransaction{
Tokenname: tokenname,
Type: types.PrivacyTypePrivacy2Privacy,
Amount: amount,
Note: note,
Pubkeypair: pubkeypair,
From: sender,
Mixcount: defaultPrivacyMixCount,
Expire: expire,
}
ctx := jsonclient.NewRPCCtx(rpcLaddr, "privacy.CreateRawTransaction", params, nil)
ctx.RunWithoutMarshal()
}
// CreatePriv2PubTxCmd create a privacy to public transaction
func CreatePriv2PubTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "priv2pub",
Short: "Create a privacy to public transaction",
Run: createPriv2PubTx,
}
createPriv2PubTxFlags(cmd)
return cmd
}
func createPriv2PubTxFlags(cmd *cobra.Command) {
cmd.Flags().Float64P("amount", "a", 0.0, "transfer amount, at most 4 decimal places")
cmd.MarkFlagRequired("amount")
cmd.Flags().StringP("from", "f", "", "from account address")
cmd.MarkFlagRequired("from")
cmd.Flags().StringP("to", "o", "", "to account address")
cmd.MarkFlagRequired("to")
cmd.Flags().StringP("tokenname", "t", "BTY", "token name")
cmd.Flags().StringP("note", "n", "", "note for transaction")
cmd.Flags().Int64P("expire", "", 0, "transfer expire, default one hour")
cmd.Flags().IntP("expiretype", "", 1, "0: height 1: time default is 1")
}
func createPriv2PubTx(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
amount := commandtypes.GetAmountValue(cmd, "amount")
tokenname, _ := cmd.Flags().GetString("tokenname")
from, _ := cmd.Flags().GetString("from")
to, _ := cmd.Flags().GetString("to")
note, _ := cmd.Flags().GetString("note")
expire, _ := cmd.Flags().GetInt64("expire")
expiretype, _ := cmd.Flags().GetInt("expiretype")
if expiretype == 0 {
if expire <= 0 {
fmt.Println("Invalid expire. expire must large than 0 in expiretype==0, expire", expire)
return
}
} else if expiretype == 1 {
if expire <= 0 {
expire = int64(time.Hour / time.Second)
}
} else {
fmt.Println("Invalid expiretype", expiretype)
return
}
params := types.ReqCreateTransaction{
Tokenname: tokenname,
Type: types.PrivacyTypePrivacy2Public,
Amount: amount,
Note: note,
From: from,
To: to,
Mixcount: defaultPrivacyMixCount,
Expire: expire,
}
ctx := jsonclient.NewRPCCtx(rpcLaddr, "privacy.CreateRawTransaction", params, nil)
ctx.RunWithoutMarshal()
}
......@@ -140,6 +140,7 @@ type RPC struct {
GrpcFuncBlacklist []string `protobuf:"bytes,8,rep,name=grpcFuncBlacklist" json:"grpcFuncBlacklist,omitempty"`
MainnetJrpcAddr string `protobuf:"bytes,9,opt,name=mainnetJrpcAddr" json:"mainnetJrpcAddr,omitempty"`
EnableTLS bool `protobuf:"varint,10,opt,name=enableTLS" json:"enableTLS,omitempty"`
EnableTrace bool `protobuf:"varint,10,opt,name=enableTrace" json:"enableTrace,omitempty"`
CertFile string `protobuf:"varint,11,opt,name=certFile" json:"certFile,omitempty"`
KeyFile string `protobuf:"varint,12,opt,name=keyFile" json:"keyFile,omitempty"`
}
......
......@@ -447,6 +447,20 @@ func getTo(payload interface{}) (string, bool) {
return "", false
}
//IsAssetsTransfer 是否是资产转移相关的交易
func IsAssetsTransfer(payload interface{}) bool {
if _, ok := payload.(*AssetsTransfer); ok {
return true
}
if _, ok := payload.(*AssetsWithdraw); ok {
return true
}
if _, ok := payload.(*AssetsTransferToExec); ok {
return true
}
return false
}
//Amounter 转账金额
type Amounter interface {
GetAmount() int64
......
......@@ -133,3 +133,10 @@ func TestCallCreateTx(t *testing.T) {
fee, _ = tx.GetRealFee(GInt("MinFee"))
assert.Equal(t, tx.Fee, fee)
}
func TestIsAssetsTransfer(t *testing.T) {
assert.Equal(t, true, IsAssetsTransfer(&AssetsTransfer{}))
assert.Equal(t, true, IsAssetsTransfer(&AssetsWithdraw{}))
assert.Equal(t, true, IsAssetsTransfer(&AssetsTransferToExec{}))
assert.Equal(t, false, IsAssetsTransfer(&Transaction{}))
}
......@@ -54,6 +54,7 @@ import (
"strconv"
"strings"
"time"
"unicode/utf8"
"github.com/33cn/chain33/common"
"github.com/golang/protobuf/proto"
......@@ -72,6 +73,9 @@ type Marshaler struct {
// Whether to render fields with zero values.
EmitDefaults bool
//Enable utf8 bytes to string
EnableUTF8BytesToString bool
// A string to indent each level by. The presence of this field will
// also cause a space to appear between the field separator and
// value, and for newlines to be appear between fields and array
......@@ -532,7 +536,13 @@ func (m *Marshaler) marshalValue(out *errWriter, prop *proto.Properties, v refle
return out.err
}
out.write(`"`)
out.write(common.ToHex(v.Interface().([]byte)))
data := v.Interface().([]byte)
//开启这个选项后,会把utf8的字符串转化成string,而不会弄成hex
if m.EnableUTF8BytesToString && utf8.Valid(data) {
out.write(string(data))
} else {
out.write(common.ToHex(data))
}
out.write(`"`)
return out.err
}
......@@ -672,6 +682,9 @@ type Unmarshaler struct {
// failing to unmarshal.
AllowUnknownFields bool
//Enable utf8 bytes to string
EnableUTF8BytesToString bool
// A custom URL resolver to use when unmarshaling Any messages from JSON.
// If unset, the default resolution strategy is to extract the
// fully-qualified type name from the type URL and pass that to
......@@ -1041,7 +1054,7 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe
if err != nil {
return err
}
b, err := parseBytes(hexstr)
b, err := parseBytes(hexstr, u.EnableUTF8BytesToString)
if err != nil {
return err
}
......@@ -1317,7 +1330,7 @@ func checkRequiredFieldsInValue(v reflect.Value) error {
//ErrBytesFormat 错误的bytes 类型
var ErrBytesFormat = errors.New("ErrBytesFormat")
func parseBytes(jsonstr string) ([]byte, error) {
func parseBytes(jsonstr string, enableUTF8BytesToString bool) ([]byte, error) {
if jsonstr == "" {
return []byte{}, nil
}
......@@ -1327,5 +1340,10 @@ func parseBytes(jsonstr string) ([]byte, error) {
if strings.HasPrefix(jsonstr, "0x") || strings.HasPrefix(jsonstr, "0X") {
return common.FromHex(jsonstr)
}
//字符串不是 hex 格式, 也不是 str:// 格式,但是是一个普通的utf8 字符串
//那么强制转化为bytes, 注意这个选项默认不开启.
if utf8.ValidString(jsonstr) && enableUTF8BytesToString {
return []byte(jsonstr), nil
}
return nil, ErrBytesFormat
}
......@@ -214,6 +214,12 @@ func JSONToPB(data []byte, msg proto.Message) error {
return jsonpb.Unmarshal(bytes.NewReader(data), msg)
}
//JSONToPBUTF8 默认解码utf8的字符串成bytes
func JSONToPBUTF8(data []byte, msg proto.Message) error {
decode := &jsonpb.Unmarshaler{EnableUTF8BytesToString: true}
return decode.Unmarshal(bytes.NewReader(data), msg)
}
//Hash 计算叶子节点的hash
func (leafnode *LeafNode) Hash() []byte {
data, err := proto.Marshal(leafnode)
......@@ -430,6 +436,16 @@ func PBToJSON(r Message) ([]byte, error) {
return buf.Bytes(), nil
}
// PBToJSONUTF8 消息类型转换
func PBToJSONUTF8(r Message) ([]byte, error) {
encode := &jsonpb.Marshaler{EmitDefaults: true, EnableUTF8BytesToString: true}
var buf bytes.Buffer
if err := encode.Marshal(&buf, r); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
//MustPBToJSON panic when error
func MustPBToJSON(req Message) []byte {
data, err := PBToJSON(req)
......
......@@ -153,6 +153,30 @@ func TestProtoToJson(t *testing.T) {
assert.Equal(t, dr.Msg, []byte{})
}
func TestJsonpbUTF8(t *testing.T) {
r := &Reply{Msg: []byte("OK")}
b, err := PBToJSONUTF8(r)
assert.Nil(t, err)
assert.Equal(t, b, []byte(`{"isOk":false,"msg":"OK"}`))
var newreply Reply
err = JSONToPBUTF8(b, &newreply)
assert.Nil(t, err)
assert.Equal(t, r, &newreply)
}
func TestJsonpb(t *testing.T) {
r := &Reply{Msg: []byte("OK")}
b, err := PBToJSON(r)
assert.Nil(t, err)
assert.Equal(t, b, []byte(`{"isOk":false,"msg":"0x4f4b"}`))
var newreply Reply
err = JSONToPB(b, &newreply)
assert.Nil(t, err)
assert.Equal(t, r, &newreply)
}
func TestHex(t *testing.T) {
s := "0x4f4b"
b, err := common.FromHex(s)
......
......@@ -40,8 +40,6 @@ import (
"github.com/33cn/chain33/store"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/wallet"
"golang.org/x/net/trace"
"google.golang.org/grpc"
"google.golang.org/grpc/grpclog"
)
......@@ -116,9 +114,6 @@ func RunChain33(name string) {
http.ListenAndServe("localhost:6060", nil)
}
}()
//set trace
grpc.EnableTracing = true
go startTrace()
//set maxprocs
runtime.GOMAXPROCS(cpuNum)
//开始区块链模块加载
......@@ -201,16 +196,6 @@ func RunChain33(name string) {
q.Start()
}
// 开启trace
func startTrace() {
trace.AuthRequest = func(req *http.Request) (any, sensitive bool) {
return true, true
}
go http.ListenAndServe("localhost:50051", nil)
log.Info("Trace listen on localhost:50051")
}
func createFile(filename string) (*os.File, error) {
f, err := os.OpenFile(filename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
......
......@@ -95,7 +95,7 @@ func (wallet *Wallet) ProcSignRawTx(unsigned *types.ReqSignRawTx) (string, error
return "", err
}
tx.SetExpire(time.Duration(expire))
if policy, ok := wcom.PolicyContainer[string(tx.Execer)]; ok {
if policy, ok := wcom.PolicyContainer[string(types.GetParaExec(tx.Execer))]; ok {
// 尝试让策略自己去完成签名
needSysSign, signtx, err := policy.SignTransaction(key, unsigned)
if !needSysSign {
......@@ -909,7 +909,7 @@ func (wallet *Wallet) ProcWalletAddBlock(block *types.BlockDetail) {
newbatch := wallet.walletStore.NewBatch(true)
for index := 0; index < txlen; index++ {
tx := block.Block.Txs[index]
execer := string(tx.Execer)
execer := string(types.GetParaExec(tx.Execer))
// 执行钱包业务逻辑策略
if policy, ok := wcom.PolicyContainer[execer]; ok {
wtxdetail := policy.OnAddBlockTx(block, tx, int32(index), newbatch)
......@@ -1031,7 +1031,7 @@ func (wallet *Wallet) ProcWalletDelBlock(block *types.BlockDetail) {
heightstr := fmt.Sprintf("%018d", blockheight)
tx := block.Block.Txs[index]
execer := string(tx.Execer)
execer := string(types.GetParaExec(tx.Execer))
// 执行钱包业务逻辑策略
if policy, ok := wcom.PolicyContainer[execer]; ok {
wtxdetail := policy.OnDeleteBlockTx(block, tx, int32(index), newbatch)
......
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