Commit 9cd7511f authored by linj's avatar linj Committed by vipwzw

update-chain33

parent 94196411
...@@ -28,6 +28,10 @@ wget 127.0.0.1:8866 --no-proxy --post-data='{"id" : 1 , "method" : "ShowMinerAcc ...@@ -28,6 +28,10 @@ wget 127.0.0.1:8866 --no-proxy --post-data='{"id" : 1 , "method" : "ShowMinerAcc
1. 是否有某个挖矿帐号, 一个小时挖矿所得为0, 可能是挖矿机器出故障了 1. 是否有某个挖矿帐号, 一个小时挖矿所得为0, 可能是挖矿机器出故障了
1. 增涨不到预期的50% 1. 增涨不到预期的50%
1. 不再监控这个点: 在预期能挖到币的两倍时间间隔内, 挖到的币为0。 挖矿有波动, 在进行预警的几天里, 这个有很多误报。 1. 不再监控这个点: 在预期能挖到币的两倍时间间隔内, 挖到的币为0。 挖矿有波动, 在进行预警的几天里, 这个有很多误报。
1. 数据获得失败报警
1. result 里面 null
1. 监控机器 heartbeat 表明监控机器没有宕机
``` ```
{ {
"id" : 1, "id" : 1,
......
...@@ -251,7 +251,7 @@ func TestSameTx(t *testing.T) { ...@@ -251,7 +251,7 @@ func TestSameTx(t *testing.T) {
func TestExecBlock(t *testing.T) { func TestExecBlock(t *testing.T) {
mock33 := newMockNode() mock33 := newMockNode()
defer mock33.Close() defer mock33.Close()
block := util.CreateNoneBlock(mock33.GetGenesisKey(), 10) block := util.CreateCoinsBlock(mock33.GetGenesisKey(), 1)
util.ExecBlock(mock33.GetClient(), nil, block, false, true) util.ExecBlock(mock33.GetClient(), nil, block, false, true)
} }
......
...@@ -103,3 +103,21 @@ func TestNewParaClient(t *testing.T) { ...@@ -103,3 +103,21 @@ func TestNewParaClient(t *testing.T) {
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, reply.Hash, []byte("hello")) assert.Equal(t, reply.Hash, []byte("hello"))
} }
func TestNewMainChainClient(t *testing.T) {
grpcClient1, err := grpcclient.NewMainChainClient("")
assert.Nil(t, err)
grpcClient2, err := grpcclient.NewMainChainClient("")
assert.Nil(t, err)
if grpcClient1 != grpcClient2 {
t.Error("grpc client is the same")
}
grpcClient3, err := grpcclient.NewMainChainClient("127.0.0.1")
assert.Nil(t, err)
grpcClient4, err := grpcclient.NewMainChainClient("127.0.0.1")
assert.Nil(t, err)
if grpcClient3 == grpcClient4 {
t.Error("grpc client is not the same")
}
}
package grpcclient package grpcclient
import ( import (
"sync"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
"google.golang.org/grpc" "google.golang.org/grpc"
) )
...@@ -8,8 +10,17 @@ import ( ...@@ -8,8 +10,17 @@ import (
// paraChainGrpcRecSize 平行链receive最大100M // paraChainGrpcRecSize 平行链receive最大100M
const paraChainGrpcRecSize = 100 * 1024 * 1024 const paraChainGrpcRecSize = 100 * 1024 * 1024
var mu sync.Mutex
var defaultClient types.Chain33Client
//NewMainChainClient 创建一个平行链的 主链 grpc chain33 客户端 //NewMainChainClient 创建一个平行链的 主链 grpc chain33 客户端
func NewMainChainClient(grpcaddr string) (types.Chain33Client, error) { func NewMainChainClient(grpcaddr string) (types.Chain33Client, error) {
mu.Lock()
defer mu.Unlock()
if grpcaddr == "" && defaultClient != nil {
return defaultClient, nil
}
paraRemoteGrpcClient := types.Conf("config.consensus.sub.para").GStr("ParaRemoteGrpcClient") paraRemoteGrpcClient := types.Conf("config.consensus.sub.para").GStr("ParaRemoteGrpcClient")
if grpcaddr != "" { if grpcaddr != "" {
paraRemoteGrpcClient = grpcaddr paraRemoteGrpcClient = grpcaddr
...@@ -24,5 +35,8 @@ func NewMainChainClient(grpcaddr string) (types.Chain33Client, error) { ...@@ -24,5 +35,8 @@ func NewMainChainClient(grpcaddr string) (types.Chain33Client, error) {
return nil, err return nil, err
} }
grpcClient := types.NewChain33Client(conn) grpcClient := types.NewChain33Client(conn)
if grpcaddr == "" {
defaultClient = grpcClient
}
return grpcClient, nil return grpcClient, nil
} }
...@@ -14,7 +14,8 @@ import ( ...@@ -14,7 +14,8 @@ import (
func TestMethodCall(t *testing.T) { func TestMethodCall(t *testing.T) {
action := &CoinsAction{Value: &CoinsAction_Transfer{Transfer: &types.AssetsTransfer{}}} action := &CoinsAction{Value: &CoinsAction_Transfer{Transfer: &types.AssetsTransfer{}}}
funclist := types.ListMethod(action) funclist := types.ListMethod(action)
name, ty, v := types.GetActionValue(action, funclist) name, ty, v, err := types.GetActionValue(action, funclist)
assert.Nil(t, err)
assert.Equal(t, int32(0), ty) assert.Equal(t, int32(0), ty)
assert.Equal(t, "Transfer", name) assert.Equal(t, "Transfer", name)
assert.Equal(t, &types.AssetsTransfer{}, v.Interface()) assert.Equal(t, &types.AssetsTransfer{}, v.Interface())
...@@ -44,9 +45,31 @@ func BenchmarkGetActionValue(b *testing.B) { ...@@ -44,9 +45,31 @@ func BenchmarkGetActionValue(b *testing.B) {
funclist := types.ListMethod(action) funclist := types.ListMethod(action)
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
action, ty, _ := types.GetActionValue(action, funclist) action, ty, _, _ := types.GetActionValue(action, funclist)
if action != "Transfer" || ty != 0 { if action != "Transfer" || ty != 0 {
b.Fatal(action) b.Fatal(action)
} }
} }
} }
func BenchmarkDecodePayload(b *testing.B) {
action := &CoinsAction{Value: &CoinsAction_Transfer{Transfer: &types.AssetsTransfer{}}}
payload := types.Encode(action)
tx := &types.Transaction{Payload: payload}
ty := NewType()
b.ResetTimer()
for i := 0; i < b.N; i++ {
ty.DecodePayload(tx)
}
}
func BenchmarkDecodePayloadValue(b *testing.B) {
b.ReportAllocs()
action := &CoinsAction{Value: &CoinsAction_Transfer{Transfer: &types.AssetsTransfer{}}, Ty: CoinsActionTransfer}
payload := types.Encode(action)
tx := &types.Transaction{Payload: payload}
ty := NewType()
b.ResetTimer()
for i := 0; i < b.N; i++ {
ty.DecodePayloadValue(tx)
}
}
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
package types package types
import ( import (
"reflect"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
) )
...@@ -72,6 +74,50 @@ func (c *CoinsType) GetTypeMap() map[string]int32 { ...@@ -72,6 +74,50 @@ func (c *CoinsType) GetTypeMap() map[string]int32 {
return actionName return actionName
} }
//DecodePayloadValue 为了性能考虑,coins 是最常用的合约,我们这里不用反射吗,做了特殊化的优化
func (c *CoinsType) DecodePayloadValue(tx *types.Transaction) (string, reflect.Value, error) {
if txc, ok := types.TxCacheGet(tx); ok {
return txc.GetPayloadValue()
}
txc := types.NewTransactionCache(tx)
name, value, err := c.decodePayloadValue(tx)
txc.SetPayloadValue(name, value, err)
types.TxCacheSet(tx, txc)
return name, value, err
}
func (c *CoinsType) decodePayloadValue(tx *types.Transaction) (string, reflect.Value, error) {
var action CoinsAction
if tx.GetPayload() == nil {
return "", reflect.ValueOf(nil), types.ErrActionNotSupport
}
err := types.Decode(tx.Payload, &action)
if err != nil {
return "", reflect.ValueOf(nil), err
}
var name string
var value types.Message
switch action.Ty {
case CoinsActionTransfer:
name = "Transfer"
value = action.GetTransfer()
case CoinsActionTransferToExec:
name = "TransferToExec"
value = action.GetTransferToExec()
case CoinsActionWithdraw:
name = "Withdraw"
value = action.GetWithdraw()
case CoinsActionGenesis:
name = "Genesis"
value = action.GetGenesis()
}
if value == nil {
return "", reflect.ValueOf(nil), types.ErrActionNotSupport
}
return name, reflect.ValueOf(value), nil
}
// RPC_Default_Process default process fo rpc // RPC_Default_Process default process fo rpc
func (c *CoinsType) RPC_Default_Process(action string, msg interface{}) (*types.Transaction, error) { func (c *CoinsType) RPC_Default_Process(action string, msg interface{}) (*types.Transaction, error) {
var create *types.CreateTx var create *types.CreateTx
......
...@@ -422,7 +422,7 @@ func (base *ExecTypeBase) GetRealToAddr(tx *Transaction) string { ...@@ -422,7 +422,7 @@ func (base *ExecTypeBase) GetRealToAddr(tx *Transaction) string {
return tx.To return tx.To
} }
//平行链中的处理方式 //平行链中的处理方式
_, v, err := base.DecodePayloadValue(tx) _, v, err := base.child.DecodePayloadValue(tx)
if err != nil { if err != nil {
return tx.To return tx.To
} }
...@@ -468,7 +468,7 @@ type Amounter interface { ...@@ -468,7 +468,7 @@ type Amounter interface {
//Amount 获取tx交易中的转账金额 //Amount 获取tx交易中的转账金额
func (base *ExecTypeBase) Amount(tx *Transaction) (int64, error) { func (base *ExecTypeBase) Amount(tx *Transaction) (int64, error) {
_, v, err := base.DecodePayloadValue(tx) _, v, err := base.child.DecodePayloadValue(tx)
if err != nil { if err != nil {
return 0, err return 0, err
} }
...@@ -503,14 +503,22 @@ func (base *ExecTypeBase) DecodePayload(tx *Transaction) (Message, error) { ...@@ -503,14 +503,22 @@ func (base *ExecTypeBase) DecodePayload(tx *Transaction) (Message, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if IsNilP(payload) {
return nil, ErrDecode
}
return payload, nil return payload, nil
} }
//DecodePayloadValue 解析tx交易中的payload具体Value值 //DecodePayloadValue 解析tx交易中的payload具体Value值
func (base *ExecTypeBase) DecodePayloadValue(tx *Transaction) (string, reflect.Value, error) { func (base *ExecTypeBase) DecodePayloadValue(tx *Transaction) (string, reflect.Value, error) {
if txc, ok := txCache.Get(tx); ok {
return txc.(*TransactionCache).GetPayloadValue()
}
txc := NewTransactionCache(tx)
name, value, err := base.decodePayloadValue(tx)
txc.SetPayloadValue(name, value, err)
txCache.Add(tx, txc)
return name, value, err
}
func (base *ExecTypeBase) decodePayloadValue(tx *Transaction) (string, reflect.Value, error) {
if base.child == nil { if base.child == nil {
return "", nilValue, ErrActionNotSupport return "", nilValue, ErrActionNotSupport
} }
...@@ -519,10 +527,9 @@ func (base *ExecTypeBase) DecodePayloadValue(tx *Transaction) (string, reflect.V ...@@ -519,10 +527,9 @@ func (base *ExecTypeBase) DecodePayloadValue(tx *Transaction) (string, reflect.V
tlog.Error("DecodePayload", "err", err, "exec", string(tx.Execer)) tlog.Error("DecodePayload", "err", err, "exec", string(tx.Execer))
return "", nilValue, err return "", nilValue, err
} }
name, ty, val := GetActionValue(action, base.child.GetFuncMap()) name, ty, val, err := GetActionValue(action, base.child.GetFuncMap())
if IsNil(val) { if err != nil {
tlog.Error("GetActionValue is nil") return "", nilValue, err
return "", nilValue, ErrActionNotSupport
} }
typemap := base.child.GetTypeMap() typemap := base.child.GetTypeMap()
//check types is ok //check types is ok
...@@ -769,7 +776,7 @@ func (base *ExecTypeBase) CreateTransaction(action string, data Message) (tx *Tr ...@@ -769,7 +776,7 @@ func (base *ExecTypeBase) CreateTransaction(action string, data Message) (tx *Tr
// GetAssets 获取资产信息 // GetAssets 获取资产信息
func (base *ExecTypeBase) GetAssets(tx *Transaction) ([]*Asset, error) { func (base *ExecTypeBase) GetAssets(tx *Transaction) ([]*Asset, error) {
_, v, err := base.DecodePayloadValue(tx) _, v, err := base.child.DecodePayloadValue(tx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -95,12 +95,13 @@ func ListMethodByType(typ reflect.Type) map[string]reflect.Method { ...@@ -95,12 +95,13 @@ func ListMethodByType(typ reflect.Type) map[string]reflect.Method {
var nilValue = reflect.ValueOf(nil) var nilValue = reflect.ValueOf(nil)
// GetActionValue 获取执行器的action value // GetActionValue 获取执行器的action value
func GetActionValue(action interface{}, funclist map[string]reflect.Method) (vname string, vty int32, v reflect.Value) { func GetActionValue(action interface{}, funclist map[string]reflect.Method) (vname string, vty int32, v reflect.Value, err error) {
defer func() { defer func() {
if e := recover(); e != nil { if e := recover(); e != nil {
vname = "" vname = ""
vty = 0 vty = 0
v = nilValue v = nilValue
err = ErrDecode
} }
}() }()
var ty int32 var ty int32
...@@ -109,22 +110,25 @@ func GetActionValue(action interface{}, funclist map[string]reflect.Method) (vna ...@@ -109,22 +110,25 @@ func GetActionValue(action interface{}, funclist map[string]reflect.Method) (vna
} }
value := reflect.ValueOf(action) value := reflect.ValueOf(action)
if _, ok := funclist["GetValue"]; !ok { if _, ok := funclist["GetValue"]; !ok {
return "", 0, nilValue return "", 0, nilValue, ErrDecode
} }
rcvr := funclist["GetValue"].Func.Call([]reflect.Value{value}) rcvr := funclist["GetValue"].Func.Call([]reflect.Value{value})
elem := rcvr[0].Elem() elem := rcvr[0].Elem()
sname := elem.Type().String() sname := elem.Type().String()
index := strings.LastIndex(sname, "_") index := strings.LastIndex(sname, "_")
if index == -1 || index == (len(sname)-1) { if index == -1 || index == (len(sname)-1) {
return "", 0, nilValue return "", 0, nilValue, ErrDecode
} }
tyname := sname[index+1:] tyname := sname[index+1:]
funcname := "Get" + tyname funcname := "Get" + tyname
if _, ok := funclist[funcname]; !ok { if _, ok := funclist[funcname]; !ok {
return "", 0, nilValue return "", 0, nilValue, ErrDecode
} }
val := funclist[funcname].Func.Call([]reflect.Value{value}) val := funclist[funcname].Func.Call([]reflect.Value{value})
return tyname, ty, val[0] if len(val) == 0 || val[0].IsNil() {
return "", 0, nilValue, ErrDecode
}
return tyname, ty, val[0], nil
} }
// IsOK 是否存在 // IsOK 是否存在
......
...@@ -8,8 +8,11 @@ import ( ...@@ -8,8 +8,11 @@ import (
"bytes" "bytes"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"reflect"
"time" "time"
"github.com/hashicorp/golang-lru"
"strconv" "strconv"
"github.com/33cn/chain33/common" "github.com/33cn/chain33/common"
...@@ -21,8 +24,35 @@ var ( ...@@ -21,8 +24,35 @@ var (
bCoins = []byte("coins") bCoins = []byte("coins")
bToken = []byte("token") bToken = []byte("token")
withdraw = "withdraw" withdraw = "withdraw"
txCache *lru.Cache
) )
func init() {
var err error
txCache, err = lru.New(10240)
if err != nil {
panic(err)
}
}
//TxCacheGet 某些交易的cache 加入缓存中,防止重复进行解析或者计算
func TxCacheGet(tx *Transaction) (*TransactionCache, bool) {
txc, ok := txCache.Get(tx)
if !ok {
return nil, ok
}
return txc.(*TransactionCache), ok
}
//TxCacheSet 设置 cache
func TxCacheSet(tx *Transaction, txc *TransactionCache) {
if txc == nil {
txCache.Remove(tx)
return
}
txCache.Add(tx, txc)
}
// CreateTxGroup 创建组交易 // CreateTxGroup 创建组交易
func CreateTxGroup(txs []*Transaction) (*Transactions, error) { func CreateTxGroup(txs []*Transaction) (*Transactions, error) {
if len(txs) < 2 { if len(txs) < 2 {
...@@ -204,6 +234,9 @@ type TransactionCache struct { ...@@ -204,6 +234,9 @@ type TransactionCache struct {
signok int //init 0, ok 1, err 2 signok int //init 0, ok 1, err 2
checkok error //init 0, ok 1, err 2 checkok error //init 0, ok 1, err 2
checked bool checked bool
payload reflect.Value
plname string
plerr error
} }
//NewTransactionCache new交易缓存 //NewTransactionCache new交易缓存
...@@ -219,6 +252,28 @@ func (tx *TransactionCache) Hash() []byte { ...@@ -219,6 +252,28 @@ func (tx *TransactionCache) Hash() []byte {
return tx.hash return tx.hash
} }
//SetPayloadValue 设置payload 的cache
func (tx *TransactionCache) SetPayloadValue(plname string, payload reflect.Value, plerr error) {
tx.payload = payload
tx.plerr = plerr
tx.plname = plname
}
//GetPayloadValue 设置payload 的cache
func (tx *TransactionCache) GetPayloadValue() (plname string, payload reflect.Value, plerr error) {
if tx.plerr != nil || tx.plname != "" {
return tx.plname, tx.payload, tx.plerr
}
exec := LoadExecutorType(string(tx.Execer))
if exec == nil {
tx.SetPayloadValue("", reflect.ValueOf(nil), ErrExecNotFound)
return "", reflect.ValueOf(nil), ErrExecNotFound
}
plname, payload, plerr = exec.DecodePayloadValue(tx.Tx())
tx.SetPayloadValue(plname, payload, plerr)
return
}
//Size 交易缓存的大小 //Size 交易缓存的大小
func (tx *TransactionCache) Size() int { func (tx *TransactionCache) Size() int {
if tx.size == 0 { if tx.size == 0 {
......
...@@ -289,15 +289,15 @@ func (mock *Chain33Mock) Close() { ...@@ -289,15 +289,15 @@ func (mock *Chain33Mock) Close() {
} }
func (mock *Chain33Mock) closeNoLock() { func (mock *Chain33Mock) closeNoLock() {
mock.chain.Close() mock.network.Close()
mock.store.Close() mock.rpc.Close()
mock.mem.Close() mock.mem.Close()
mock.cs.Close()
mock.exec.Close() mock.exec.Close()
mock.cs.Close()
mock.wallet.Close() mock.wallet.Close()
mock.network.Close() mock.chain.Close()
mock.store.Close()
mock.client.Close() mock.client.Close()
mock.rpc.Close()
os.RemoveAll(mock.datadir) os.RemoveAll(mock.datadir)
} }
......
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