Commit c5d585c4 authored by 陈德海's avatar 陈德海

mempool add get proper fee

parent 9d75053f
......@@ -73,7 +73,7 @@ poolCacheSize=10240
[mempool.sub.score]
poolCacheSize=10240
timeParam=1 #时间占价格比例
priceConstant=1544 #手续费相对于时间的一个合适的常量,取当前unxi时间戳前四位数,排序时手续费高1e-5~=快1s
priceConstant=3 #手续费相对于时间的一个的常量,排队时手续费高1e3的分数~=快1h的分数
pricePower=1 #常量比例
[mempool.sub.price]
......
......@@ -130,3 +130,23 @@ func (cache *Queue) Walk(count int, cb func(value *mempool.Item) bool) {
return i != count
})
}
// GetProperFee 获取合适的手续费,取前100的平均价格
func (cache *Queue) GetProperFee() int64 {
var sumFee int64
var properFee int64
if cache.Size() == 0 {
return cache.subConfig.ProperFee
}
i := 0
cache.Walk(0, func(tx *mempool.Item) bool {
if i == 100 {
return false
}
sumFee += tx.Value.Fee
i++
return true
})
properFee = sumFee / int64(i)
return properFee
}
......@@ -113,9 +113,9 @@ func TestTimeCompetition(t *testing.T) {
func TestPriceCompetition(t *testing.T) {
cache := initEnv(1)
cache.Push(item1)
cache.Push(item3)
cache.Push(item4)
assert.Equal(t, false, cache.Exist(string(item1.Value.Hash())))
assert.Equal(t, false, cache.Exist(string(item3.Value.Hash())))
assert.Equal(t, true, cache.Exist(string(item4.Value.Hash())))
}
......@@ -149,3 +149,13 @@ func TestQueueDirection(t *testing.T) {
assert.Equal(t, 5, i)
assert.Equal(t, true, lastScore == cache.txList.GetIterator().Last().Score)
}
func TestGetProperFee(t *testing.T) {
cache := initEnv(0)
assert.Equal(t, cache.subConfig.ProperFee, cache.GetProperFee())
cache.Push(item1)
cache.Push(item4)
cache.GetProperFee()
assert.Equal(t, (item1.Value.Fee+item4.Value.Fee)/2, cache.GetProperFee())
}
......@@ -75,7 +75,7 @@ poolCacheSize=10240
[mempool.sub.score]
poolCacheSize=10240
timeParam=1 #时间占价格比例
priceConstant=1544 #手续费相对于时间的一个合适的常量,取当前unxi时间戳前四位数,排序时手续费高1e-5~=快1s
priceConstant=3 #手续费相对于时间的一个的常量,排队时手续费高1e3的分数~=快1h的分数
pricePower=1 #常量比例
[mempool.sub.price]
......
......@@ -11,6 +11,7 @@ import (
type subConfig struct {
PoolCacheSize int64 `json:"poolCacheSize"`
ProperFee int64 `json:"properFee"`
}
func init() {
......@@ -25,6 +26,9 @@ func New(cfg *types.Mempool, sub []byte) queue.Module {
if subcfg.PoolCacheSize == 0 {
subcfg.PoolCacheSize = cfg.PoolCacheSize
}
if subcfg.ProperFee == 0 {
subcfg.ProperFee = cfg.MinTxFee
}
c.SetQueueCache(NewQueue(subcfg))
return c
}
......@@ -3,6 +3,7 @@ package score
import (
"bytes"
"encoding/gob"
"time"
"github.com/33cn/chain33/common/skiplist"
"github.com/33cn/chain33/system/mempool"
......@@ -36,7 +37,8 @@ func (cache *Queue) newSkipValue(item *mempool.Item) (*skiplist.SkipValue, error
return nil, err
}
size := len(buf.Bytes())
return &skiplist.SkipValue{Score: cache.subConfig.PriceConstant*(item.Value.Fee/int64(size))*cache.subConfig.PricePower - cache.subConfig.TimeParam*item.EnterTime, Value: item}, nil
return &skiplist.SkipValue{Score: cache.subConfig.PriceConstant*(item.Value.Fee/int64(size))*
cache.subConfig.PricePower - cache.subConfig.TimeParam*item.EnterTime, Value: item}, nil
}
// Exist 是否存在
......@@ -122,3 +124,26 @@ func (cache *Queue) Walk(count int, cb func(value *mempool.Item) bool) {
return i != count
})
}
// GetProperFee 获取合适的手续费
func (cache *Queue) GetProperFee() int64 {
var sumScore int64
var properFee int64
if cache.Size() == 0 {
return cache.subConfig.ProperFee
}
i := 0
cache.Walk(0, func(tx *mempool.Item) bool {
if i == 100 {
return false
}
//这里的int64(500)是一般交易的大小
sumScore += cache.subConfig.PriceConstant*tx.Value.Fee*
cache.subConfig.PricePower*int64(500) - cache.subConfig.TimeParam*tx.EnterTime
i++
return true
})
properFee = (sumScore/int64(cache.Size()) + cache.subConfig.TimeParam*time.Now().Unix()) /
(cache.subConfig.PriceConstant * cache.subConfig.PricePower * int64(500))
return properFee
}
package score
import (
"testing"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/common/crypto"
......@@ -10,6 +8,8 @@ import (
drivers "github.com/33cn/chain33/system/mempool"
"github.com/33cn/chain33/types"
"github.com/stretchr/testify/assert"
"testing"
"time"
)
var (
......@@ -21,11 +21,11 @@ var (
amount = int64(1e8)
v = &cty.CoinsAction_Transfer{Transfer: &types.AssetsTransfer{Amount: amount}}
transfer = &cty.CoinsAction{Value: v, Ty: cty.CoinsActionTransfer}
tx1 = &types.Transaction{Execer: []byte("coins"), Payload: types.Encode(transfer), Fee: 1000000, Expire: 1, To: toAddr}
tx2 = &types.Transaction{Execer: []byte("coins"), Payload: types.Encode(transfer), Fee: 1000000, Expire: 2, To: toAddr}
tx3 = &types.Transaction{Execer: []byte("coins"), Payload: types.Encode(transfer), Fee: 1000000, Expire: 3, To: toAddr}
tx4 = &types.Transaction{Execer: []byte("coins"), Payload: types.Encode(transfer), Fee: 2000000, Expire: 4, To: toAddr}
tx5 = &types.Transaction{Execer: []byte("coins"), Payload: types.Encode(transfer), Fee: 1000000, Expire: 5, To: toAddr}
tx1 = &types.Transaction{Execer: []byte("coins"), Payload: types.Encode(transfer), Fee: 100000, Expire: 1, To: toAddr}
tx2 = &types.Transaction{Execer: []byte("coins"), Payload: types.Encode(transfer), Fee: 100000, Expire: 2, To: toAddr}
tx3 = &types.Transaction{Execer: []byte("coins"), Payload: types.Encode(transfer), Fee: 100000, Expire: 3, To: toAddr}
tx4 = &types.Transaction{Execer: []byte("coins"), Payload: types.Encode(transfer), Fee: 200000, Expire: 4, To: toAddr}
tx5 = &types.Transaction{Execer: []byte("coins"), Payload: types.Encode(transfer), Fee: 100000, Expire: 5, To: toAddr}
item1 = &drivers.Item{Value: tx1, Priority: tx1.Fee, EnterTime: types.Now().Unix()}
item2 = &drivers.Item{Value: tx2, Priority: tx2.Fee, EnterTime: types.Now().Unix()}
item3 = &drivers.Item{Value: tx3, Priority: tx3.Fee, EnterTime: types.Now().Unix() - 1000}
......@@ -113,9 +113,9 @@ func TestTimeCompetition(t *testing.T) {
func TestPriceCompetition(t *testing.T) {
cache := initEnv(1)
cache.Push(item1)
cache.Push(item3)
cache.Push(item4)
assert.Equal(t, false, cache.Exist(string(item1.Value.Hash())))
assert.Equal(t, false, cache.Exist(string(item3.Value.Hash())))
assert.Equal(t, true, cache.Exist(string(item4.Value.Hash())))
}
......@@ -149,3 +149,19 @@ func TestQueueDirection(t *testing.T) {
assert.Equal(t, 5, i)
assert.Equal(t, true, lastScore == cache.txList.GetIterator().Last().Score)
}
func TestGetProperFee(t *testing.T) {
cache := initEnv(0)
assert.Equal(t, cache.subConfig.ProperFee, cache.GetProperFee())
cache.Push(item3)
cache.Push(item4)
cache.GetProperFee()
score3 := item3.Priority*cache.subConfig.PriceConstant*cache.subConfig.PricePower*int64(500) -
item3.EnterTime*cache.subConfig.TimeParam
score4 := item4.Priority*cache.subConfig.PriceConstant*cache.subConfig.PricePower*int64(500) -
item4.EnterTime*cache.subConfig.TimeParam
properFee := ((score3+score4)/2 + time.Now().Unix()*cache.subConfig.TimeParam) /
(cache.subConfig.PriceConstant * cache.subConfig.PricePower * int64(500))
assert.Equal(t, properFee, cache.GetProperFee())
}
......@@ -75,7 +75,7 @@ poolCacheSize=10240
[mempool.sub.score]
poolCacheSize=10240
timeParam=1 #时间占价格比例
priceConstant=1544 #手续费相对于时间的一个合适的常量,取当前unxi时间戳前四位数,排队时手续费高1e-5的分数~=快1s的分数
priceConstant=3 #手续费相对于时间的一个的常量,排队时手续费高1e3的分数~=快1h的分数
pricePower=1 #常量比例
[mempool.sub.price]
......
......@@ -14,6 +14,7 @@ type subConfig struct {
TimeParam int64 `json:"timeParam"`
PriceConstant int64 `json:"priceConstant"`
PricePower int64 `json:"pricePower"`
ProperFee int64 `json:"properFee"`
}
func init() {
......@@ -28,6 +29,9 @@ func New(cfg *types.Mempool, sub []byte) queue.Module {
if subcfg.PoolCacheSize == 0 {
subcfg.PoolCacheSize = cfg.PoolCacheSize
}
if subcfg.ProperFee == 0 {
subcfg.ProperFee = cfg.MinTxFee
}
c.SetQueueCache(NewQueue(subcfg))
return c
}
......@@ -47,6 +47,8 @@ func (m *mockMempool) SetQueueClient(q queue.Queue) {
msg.Reply(client.NewMessage(mempoolKey, types.EventReplyTxList, &types.ReplyTxList{}))
case types.EventGetLastMempool:
msg.Reply(client.NewMessage(mempoolKey, types.EventReplyTxList, &types.ReplyTxList{}))
case types.EventGetProperFee:
msg.Reply(client.NewMessage(mempoolKey, types.EventReplyProperFee, &types.ReplyProperFee{}))
default:
msg.ReplyErr("Do not support", types.ErrNotSupport)
}
......
......@@ -453,6 +453,29 @@ func (_m *QueueProtocolAPI) GetMempool() (*types.ReplyTxList, error) {
return r0, r1
}
// GetProperFee provides a mock function with given fields:
func (_m *QueueProtocolAPI) GetProperFee() (*types.ReplyProperFee, error) {
ret := _m.Called()
var r0 *types.ReplyProperFee
if rf, ok := ret.Get(0).(func() *types.ReplyProperFee); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.ReplyProperFee)
}
}
var r1 error
if rf, ok := ret.Get(1).(func() error); ok {
r1 = rf()
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetNetInfo provides a mock function with given fields:
func (_m *QueueProtocolAPI) GetNetInfo() (*types.NodeNetInfo, error) {
ret := _m.Called()
......
......@@ -468,6 +468,19 @@ func (q *QueueProtocol) GetLastMempool() (*types.ReplyTxList, error) {
return nil, types.ErrTypeAsset
}
// GetProperFee get proper fee from mempool
func (q *QueueProtocol) GetProperFee() (*types.ReplyProperFee, error) {
msg, err := q.query(mempoolKey, types.EventGetProperFee, &types.ReqNil{})
if err != nil {
log.Error("GetProperFee", "Error", err.Error())
return nil, err
}
if reply, ok := msg.GetData().(*types.ReplyProperFee); ok {
return reply, nil
}
return nil, types.ErrTypeAsset
}
// GetBlockOverview get block head detil by hash
func (q *QueueProtocol) GetBlockOverview(param *types.ReqHash) (*types.BlockOverview, error) {
if param == nil {
......
......@@ -79,6 +79,7 @@ func TestQueueProtocol(t *testing.T) {
testPeerInfo(t, api)
testGetHeaders(t, api)
testGetLastMempool(t, api)
testGetProperFee(t, api)
testGetBlockOverview(t, api)
testGetAddrOverview(t, api)
testGetBlockHash(t, api)
......@@ -341,6 +342,13 @@ func testGetLastMempool(t *testing.T, api client.QueueProtocolAPI) {
}
}
func testGetProperFee(t *testing.T, api client.QueueProtocolAPI) {
_, err := api.GetProperFee()
if err != nil {
t.Error("Call GetProperFee Failed.", err)
}
}
func testGetHeaders(t *testing.T, api client.QueueProtocolAPI) {
_, err := api.GetHeaders(&types.ReqBlocks{})
if err != nil {
......@@ -627,6 +635,7 @@ func TestJsonRPC(t *testing.T) {
testGetLastHeaderJsonRPC(t, &jrpc)
testGetMempoolJsonRPC(t, &jrpc)
testGetLastMemPoolJsonRPC(t, &jrpc)
testGetProperFeeJsonRPC(t, &jrpc)
testGenSeedsonRPC(t, &jrpc)
testGetPeerInfoJsonRPC(t, &jrpc)
testIsNtpClockSyncJsonRPC(t, &jrpc)
......@@ -723,6 +732,15 @@ func testGetLastMemPoolJsonRPC(t *testing.T, rpc *mockJRPCSystem) {
}
}
func testGetProperFeeJsonRPC(t *testing.T, rpc *mockJRPCSystem) {
var res rpctypes.ReplyProperFee
err := rpc.newRpcCtx("Chain33.GetProperFee",
nil, &res)
if err != nil {
t.Error("testGetProperFeeJsonRPC failed. Error", err)
}
}
func testGetMempoolJsonRPC(t *testing.T, rpc *mockJRPCSystem) {
var res rpctypes.ReplyTxList
err := rpc.newRpcCtx("Chain33.GetMempool",
......@@ -820,6 +838,7 @@ func TestGRPC(t *testing.T) {
testUnLockGRPC(t, &grpcMock)
testGetPeerInfoGRPC(t, &grpcMock)
testGetLastMemPoolGRPC(t, &grpcMock)
testGetProperFeeGRPC(t, &grpcMock)
testGetWalletStatusGRPC(t, &grpcMock)
testGetBlockOverviewGRPC(t, &grpcMock)
testGetAddrOverviewGRPC(t, &grpcMock)
......@@ -969,6 +988,14 @@ func testGetLastMemPoolGRPC(t *testing.T, rpc *mockGRPCSystem) {
}
}
func testGetProperFeeGRPC(t *testing.T, rpc *mockGRPCSystem) {
var res types.ReplyProperFee
err := rpc.newRpcCtx("GetProperFee", &types.ReqNil{}, &res)
if err != nil {
t.Error("Call GetProperFee Failed.", err)
}
}
func testGetPeerInfoGRPC(t *testing.T, rpc *mockGRPCSystem) {
var res types.PeerList
err := rpc.newRpcCtx("GetPeerInfo", &types.ReqNil{}, &res)
......
......@@ -24,6 +24,8 @@ type QueueProtocolAPI interface {
GetMempool() (*types.ReplyTxList, error)
// types.EventGetLastMempool
GetLastMempool() (*types.ReplyTxList, error)
// types.EventGetProperFee
GetProperFee() (*types.ReplyProperFee, error)
// +++++++++++++++ execs interfaces begin
// types.EventBlockChainQuery
Query(driver, funcname string, param types.Message) (types.Message, error)
......
......@@ -225,6 +225,12 @@ func (c *GrpcCtx) Run() (err error) {
*c.Res.(*types.ReplyTxList) = *reply
}
errRet = err
case "GetProperFee":
reply, err := rpc.GetProperFee(context.Background(), c.Params.(*types.ReqNil))
if err == nil {
*c.Res.(*types.ReplyProperFee) = *reply
}
errRet = err
case "GetWalletStatus":
reply, err := rpc.GetWalletStatus(context.Background(), c.Params.(*types.ReqNil))
if err == nil {
......
......@@ -208,6 +208,11 @@ func (g *Grpc) GetLastMemPool(ctx context.Context, in *pb.ReqNil) (*pb.ReplyTxLi
return g.cli.GetLastMempool()
}
// GetProperFee return last mempool proper fee
func (g *Grpc) GetProperFee(ctx context.Context, in *pb.ReqNil) (*pb.ReplyProperFee, error) {
return g.cli.GetProperFee()
}
// GetBlockOverview get block overview
// GetBlockOverview(parm *types.ReqHash) (*types.BlockOverview, error) //add by hyb
func (g *Grpc) GetBlockOverview(ctx context.Context, in *pb.ReqHash) (*pb.BlockOverview, error) {
......
......@@ -202,6 +202,18 @@ func TestGetLastMemPool(t *testing.T) {
testGetLastMemPoolOK(t)
}
func testGetProperFeeOK(t *testing.T) {
qapi.On("GetProperFee").Return(nil, nil)
data, err := g.GetProperFee(getOkCtx(), nil)
assert.Nil(t, err, "the error should be nil")
assert.Nil(t, data)
}
func TestGetProperFee(t *testing.T) {
testGetProperFeeOK(t)
}
//func (g *Grpc) QueryChain(ctx context.Context, in *pb.Query) (*pb.Reply, error) {
// if !g.checkWhitlist(ctx) {
// return nil, fmt.Errorf("reject")
......
......@@ -616,6 +616,18 @@ func (c *Chain33) GetLastMemPool(in types.ReqNil, result *interface{}) error {
return nil
}
// GetProperFee get contents in proper fee
func (c *Chain33) GetProperFee(in types.ReqNil, result *interface{}) error {
reply, err := c.cli.GetProperFee()
if err != nil {
return err
}
var properFee rpctypes.ReplyProperFee
properFee.ProperFee = reply.GetProperFee()
*result = &properFee
return nil
}
// GetBlockOverview get overview of block
// GetBlockOverview(parm *types.ReqHash) (*types.BlockOverview, error)
func (c *Chain33) GetBlockOverview(in rpctypes.QueryParm, result *interface{}) error {
......
......@@ -1019,6 +1019,23 @@ func TestChain33_GetLastMemPool(t *testing.T) {
mock.AssertExpectationsForObjects(t, api)
}
func TestChain33_GetProperFee(t *testing.T) {
api := new(mocks.QueueProtocolAPI)
testChain33 := newTestChain33(api)
// expected := &types.ReqBlocks{}
api.On("GetProperFee").Return(nil, errors.New("error value"))
var testResult interface{}
actual := types.ReqNil{}
err := testChain33.GetProperFee(actual, &testResult)
t.Log(err)
assert.Equal(t, nil, testResult)
assert.NotNil(t, err)
mock.AssertExpectationsForObjects(t, api)
}
func TestChain33_GetBlockOverview(t *testing.T) {
api := new(mocks.QueueProtocolAPI)
testChain33 := newTestChain33(api)
......
......@@ -173,6 +173,11 @@ type ReplyTxList struct {
Txs []*Transaction `json:"txs"`
}
// ReplyTxList reply tx list
type ReplyProperFee struct {
ProperFee int64 `json:"properFee"`
}
// ReplyHash reply hash string json
type ReplyHash struct {
Hash string `json:"hash"`
......
......@@ -22,6 +22,7 @@ func MempoolCmd() *cobra.Command {
cmd.AddCommand(
GetMempoolCmd(),
GetLastMempoolCmd(),
GetProperFeeCmd(),
)
return cmd
......@@ -80,3 +81,21 @@ func parselastMempoolTxsRes(arg interface{}) (interface{}, error) {
}
return result, nil
}
// GetProperFeeCmd get last proper fee
func GetProperFeeCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "proper_fee",
Short: "Get latest proper fee",
Run: properFee,
}
return cmd
}
func properFee(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
var res rpctypes.ReplyProperFee
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.GetProperFee", nil, &res)
ctx.SetResultCb(nil)
ctx.Run()
}
......@@ -16,6 +16,7 @@ type QueueCache interface {
Remove(hash string) error
Size() int
Walk(count int, cb func(tx *Item) bool)
GetProperFee() int64
}
// Item 为Mempool中包装交易的数据结构
......
......@@ -87,6 +87,9 @@ func (mem *Mempool) eventProcess() {
case types.EventGetAddrTxs:
// 获取mempool中对应账户(组)所有交易
mem.eventGetAddrTxs(msg)
case types.EventGetProperFee:
// 获取对应排队策略中合适的手续费
mem.eventGetProperFee(msg)
default:
}
mlog.Debug("mempool", "cost", types.Since(beg), "msg", types.GetEventName(int(msg.Ty)))
......@@ -186,6 +189,13 @@ func (mem *Mempool) eventGetAddrTxs(msg *queue.Message) {
msg.Reply(mem.client.NewMessage("", types.EventReplyAddrTxs, txlist))
}
// eventGetProperFee 获取排队策略中合适的手续费
func (mem *Mempool) eventGetProperFee(msg *queue.Message) {
properFee := mem.cache.qcache.GetProperFee()
msg.Reply(mem.client.NewMessage("rpc", types.EventReplyProperFee,
&types.ReplyProperFee{ProperFee: properFee}))
}
func (mem *Mempool) checkSign(data *queue.Message) *queue.Message {
tx, ok := data.GetData().(types.TxGroup)
if ok && tx.CheckSign() {
......
......@@ -124,8 +124,9 @@ func initEnv3() (queue.Queue, queue.Module, queue.Module, *Mempool) {
types.SetMinFee(0)
s := store.New(cfg.Store, sub.Store)
s.SetQueueClient(q.Client())
subConfig := SubConfig{cfg.Mempool.PoolCacheSize, cfg.Mempool.MinTxFee}
mem := NewMempool(cfg.Mempool)
mem.SetQueueCache(NewSimpleQueue(int(cfg.Mempool.PoolCacheSize)))
mem.SetQueueCache(NewSimpleQueue(subConfig))
mem.SetQueueClient(q.Client())
mem.Wait()
return q, chain, s, mem
......@@ -138,8 +139,9 @@ func initEnv2(size int) (queue.Queue, *Mempool) {
blockchainProcess(q)
execProcess(q)
cfg.Mempool.PoolCacheSize = int64(size)
subConfig := SubConfig{cfg.Mempool.PoolCacheSize, cfg.Mempool.MinTxFee}
mem := NewMempool(cfg.Mempool)
mem.SetQueueCache(NewSimpleQueue(size))
mem.SetQueueCache(NewSimpleQueue(subConfig))
mem.SetQueueClient(q.Client())
mem.setSync(true)
mem.SetMinFee(0)
......@@ -157,8 +159,9 @@ func initEnv(size int) (queue.Queue, *Mempool) {
blockchainProcess(q)
execProcess(q)
cfg.Mempool.PoolCacheSize = int64(size)
subConfig := SubConfig{cfg.Mempool.PoolCacheSize, cfg.Mempool.MinTxFee}
mem := NewMempool(cfg.Mempool)
mem.SetQueueCache(NewSimpleQueue(size))
mem.SetQueueCache(NewSimpleQueue(subConfig))
mem.SetQueueClient(q.Client())
mem.setSync(true)
mem.SetMinFee(types.GInt("MinFee"))
......@@ -567,6 +570,37 @@ func TestGetLatestTx(t *testing.T) {
}
}
func TestGetProperFee(t *testing.T) {
q, mem := initEnv(0)
defer q.Close()
defer mem.Close()
// add 10 txs
err := add10Tx(mem.client)
if err != nil {
t.Error("add tx error", err.Error())
return
}
msg11 := mem.client.NewMessage("mempool", types.EventTx, tx11)
mem.client.Send(msg11, true)
mem.client.Wait(msg11)
msg := mem.client.NewMessage("mempool", types.EventGetProperFee, nil)
mem.client.Send(msg, true)
reply, err := mem.client.Wait(msg)
if err != nil {
t.Error(err)
return
}
if reply.GetData().(*types.ReplyProperFee).GetProperFee() != mem.cfg.MinTxFee {
t.Error("TestGetProperFee failed", reply.GetData().(*types.ReplyProperFee).GetProperFee(), mem.cfg.MinTxFee)
}
}
func TestCheckLowFee(t *testing.T) {
q, mem := initEnv(0)
defer q.Close()
......
......@@ -9,17 +9,22 @@ import (
"github.com/33cn/chain33/types"
)
type SubConfig struct {
PoolCacheSize int64 `json:"poolCacheSize"`
ProperFee int64 `json:"properFee"`
}
//SimpleQueue 简单队列模式(默认提供一个队列,便于测试)
type SimpleQueue struct {
txList *listmap.ListMap
maxsize int
txList *listmap.ListMap
subConfig SubConfig
}
//NewSimpleQueue 创建队列
func NewSimpleQueue(cacheSize int) *SimpleQueue {
func NewSimpleQueue(subConfig SubConfig) *SimpleQueue {
return &SimpleQueue{
txList: listmap.New(),
maxsize: cacheSize,
txList: listmap.New(),
subConfig: subConfig,
}
}
......@@ -43,7 +48,7 @@ func (cache *SimpleQueue) Push(tx *Item) error {
if cache.Exist(string(hash)) {
return types.ErrTxExist
}
if cache.txList.Size() >= cache.maxsize {
if cache.txList.Size() >= int(cache.subConfig.PoolCacheSize) {
return types.ErrMemFull
}
cache.txList.Push(string(hash), tx)
......@@ -72,3 +77,8 @@ func (cache *SimpleQueue) Walk(count int, cb func(value *Item) bool) {
return i != count
})
}
// GetProperFee 获取合适的手续费
func (cache *SimpleQueue) GetProperFee() int64 {
return cache.subConfig.ProperFee
}
......@@ -12,7 +12,8 @@ import (
)
func TestCache(t *testing.T) {
cache := NewSimpleQueue(1)
subConfig := SubConfig{1, 100000}
cache := NewSimpleQueue(subConfig)
tx := &types.Transaction{Payload: []byte("123")}
hash := string(tx.Hash())
assert.Equal(t, false, cache.Exist(hash))
......@@ -38,7 +39,8 @@ func TestCache(t *testing.T) {
cache.Remove(hash)
assert.Equal(t, 0, cache.Size())
//push to item
cache = NewSimpleQueue(2)
subConfig = SubConfig{2, 100000}
cache = NewSimpleQueue(subConfig)
cache.Push(item1)
cache.Push(item2)
assert.Equal(t, 2, cache.Size())
......@@ -69,4 +71,7 @@ func TestCache(t *testing.T) {
return false
})
assert.Equal(t, 1, i)
//test timeline GetProperFee
assert.Equal(t, int64(100000), cache.GetProperFee())
}
......@@ -14,18 +14,17 @@ func init() {
drivers.Reg("timeline", New)
}
type subConfig struct {
PoolCacheSize int64 `json:"poolCacheSize"`
}
//New 创建timeline cache 结构的 mempool
func New(cfg *types.Mempool, sub []byte) queue.Module {
c := drivers.NewMempool(cfg)
var subcfg subConfig
var subcfg drivers.SubConfig
types.MustDecode(sub, &subcfg)
if subcfg.PoolCacheSize == 0 {
subcfg.PoolCacheSize = cfg.PoolCacheSize
}
c.SetQueueCache(drivers.NewSimpleQueue(int(subcfg.PoolCacheSize)))
if subcfg.ProperFee == 0 {
subcfg.ProperFee = cfg.MinTxFee
}
c.SetQueueCache(drivers.NewSimpleQueue(subcfg))
return c
}
......@@ -58,13 +58,13 @@ type Mempool struct {
// mempool队列名称,可配,timeline,score,price
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
// mempool缓存容量大小,默认10240
PoolCacheSize int64 `protobuf:"varint,1,opt,name=poolCacheSize" json:"poolCacheSize,omitempty"`
PoolCacheSize int64 `protobuf:"varint,2,opt,name=poolCacheSize" json:"poolCacheSize,omitempty"`
// 最小得交易手续费用,这个没有默认值,必填,一般是100000
MinTxFee int64 `protobuf:"varint,2,opt,name=minTxFee" json:"minTxFee,omitempty"`
ForceAccept bool `protobuf:"varint,3,opt,name=forceAccept" json:"forceAccept,omitempty"`
MinTxFee int64 `protobuf:"varint,3,opt,name=minTxFee" json:"minTxFee,omitempty"`
ForceAccept bool `protobuf:"varint,4,opt,name=forceAccept" json:"forceAccept,omitempty"`
// 每个账户在mempool中得最大交易数量,默认100
MaxTxNumPerAccount int64 `protobuf:"varint,4,opt,name=maxTxNumPerAccount" json:"maxTxNumPerAccount,omitempty"`
MaxTxLast int64 `protobuf:"varint,4,opt,name=maxTxLast" json:"maxTxLast,omitempty"`
MaxTxNumPerAccount int64 `protobuf:"varint,5,opt,name=maxTxNumPerAccount" json:"maxTxNumPerAccount,omitempty"`
MaxTxLast int64 `protobuf:"varint,6,opt,name=maxTxLast" json:"maxTxLast,omitempty"`
}
// Consensus 配置
......
......@@ -146,6 +146,11 @@ const (
EventLocalRollback = 137
EventLocalNew = 138
EventLocalClose = 139
//mempool
EventGetProperFee = 140
EventReplyProperFee = 141
//exec
EventBlockChainQuery = 212
EventConsensusQuery = 213
......@@ -290,4 +295,8 @@ var eventName = map[int]string{
EventLocalRollback: "EventLocalRollback",
EventLocalNew: "EventLocalNew",
EventLocalClose: "EventLocalClose",
//mempool
EventGetProperFee: "EventGetProperFee",
EventReplyProperFee: "EventReplyProperFee",
}
......@@ -672,6 +672,36 @@ func (_m *Chain33Client) GetLastHeader(ctx context.Context, in *types.ReqNil, op
return r0, r1
}
// GetProperFee provides a mock function with given fields: ctx, in, opts
func (_m *Chain33Client) GetProperFee(ctx context.Context, in *types.ReqNil, opts ...grpc.CallOption) (*types.ReplyProperFee, error) {
_va := make([]interface{}, len(opts))
for _i := range opts {
_va[_i] = opts[_i]
}
var _ca []interface{}
_ca = append(_ca, ctx, in)
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
var r0 *types.ReplyProperFee
if rf, ok := ret.Get(0).(func(context.Context, *types.ReqNil, ...grpc.CallOption) *types.ReplyProperFee); ok {
r0 = rf(ctx, in, opts...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.ReplyProperFee)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, *types.ReqNil, ...grpc.CallOption) error); ok {
r1 = rf(ctx, in, opts...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetLastMemPool provides a mock function with given fields: ctx, in, opts
func (_m *Chain33Client) GetLastMemPool(ctx context.Context, in *types.ReqNil, opts ...grpc.CallOption) (*types.ReplyTxList, error) {
_va := make([]interface{}, len(opts))
......
......@@ -76,6 +76,9 @@ service chain33 {
//获取最新的Mempool
rpc GetLastMemPool(ReqNil) returns (ReplyTxList) {}
//获取最新的ProperFee
rpc GetProperFee(ReqNil) returns (ReplyProperFee) {}
// 获取钱包状态
rpc GetWalletStatus(ReqNil) returns (WalletStatus) {}
//区块浏览器接口
......
......@@ -171,6 +171,10 @@ message ReplyTxList {
repeated Transaction txs = 1;
}
message ReplyProperFee {
int64 properFee = 1;
}
message TxHashList {
repeated bytes hashes = 1;
int64 count = 2;
......
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