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

mempool add get proper fee

parent 9d75053f
...@@ -73,7 +73,7 @@ poolCacheSize=10240 ...@@ -73,7 +73,7 @@ poolCacheSize=10240
[mempool.sub.score] [mempool.sub.score]
poolCacheSize=10240 poolCacheSize=10240
timeParam=1 #时间占价格比例 timeParam=1 #时间占价格比例
priceConstant=1544 #手续费相对于时间的一个合适的常量,取当前unxi时间戳前四位数,排序时手续费高1e-5~=快1s priceConstant=3 #手续费相对于时间的一个的常量,排队时手续费高1e3的分数~=快1h的分数
pricePower=1 #常量比例 pricePower=1 #常量比例
[mempool.sub.price] [mempool.sub.price]
......
...@@ -130,3 +130,23 @@ func (cache *Queue) Walk(count int, cb func(value *mempool.Item) bool) { ...@@ -130,3 +130,23 @@ func (cache *Queue) Walk(count int, cb func(value *mempool.Item) bool) {
return i != count 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) { ...@@ -113,9 +113,9 @@ func TestTimeCompetition(t *testing.T) {
func TestPriceCompetition(t *testing.T) { func TestPriceCompetition(t *testing.T) {
cache := initEnv(1) cache := initEnv(1)
cache.Push(item1) cache.Push(item3)
cache.Push(item4) 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()))) assert.Equal(t, true, cache.Exist(string(item4.Value.Hash())))
} }
...@@ -149,3 +149,13 @@ func TestQueueDirection(t *testing.T) { ...@@ -149,3 +149,13 @@ func TestQueueDirection(t *testing.T) {
assert.Equal(t, 5, i) assert.Equal(t, 5, i)
assert.Equal(t, true, lastScore == cache.txList.GetIterator().Last().Score) 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 ...@@ -75,7 +75,7 @@ poolCacheSize=10240
[mempool.sub.score] [mempool.sub.score]
poolCacheSize=10240 poolCacheSize=10240
timeParam=1 #时间占价格比例 timeParam=1 #时间占价格比例
priceConstant=1544 #手续费相对于时间的一个合适的常量,取当前unxi时间戳前四位数,排序时手续费高1e-5~=快1s priceConstant=3 #手续费相对于时间的一个的常量,排队时手续费高1e3的分数~=快1h的分数
pricePower=1 #常量比例 pricePower=1 #常量比例
[mempool.sub.price] [mempool.sub.price]
......
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
type subConfig struct { type subConfig struct {
PoolCacheSize int64 `json:"poolCacheSize"` PoolCacheSize int64 `json:"poolCacheSize"`
ProperFee int64 `json:"properFee"`
} }
func init() { func init() {
...@@ -25,6 +26,9 @@ func New(cfg *types.Mempool, sub []byte) queue.Module { ...@@ -25,6 +26,9 @@ func New(cfg *types.Mempool, sub []byte) queue.Module {
if subcfg.PoolCacheSize == 0 { if subcfg.PoolCacheSize == 0 {
subcfg.PoolCacheSize = cfg.PoolCacheSize subcfg.PoolCacheSize = cfg.PoolCacheSize
} }
if subcfg.ProperFee == 0 {
subcfg.ProperFee = cfg.MinTxFee
}
c.SetQueueCache(NewQueue(subcfg)) c.SetQueueCache(NewQueue(subcfg))
return c return c
} }
...@@ -3,6 +3,7 @@ package score ...@@ -3,6 +3,7 @@ package score
import ( import (
"bytes" "bytes"
"encoding/gob" "encoding/gob"
"time"
"github.com/33cn/chain33/common/skiplist" "github.com/33cn/chain33/common/skiplist"
"github.com/33cn/chain33/system/mempool" "github.com/33cn/chain33/system/mempool"
...@@ -36,7 +37,8 @@ func (cache *Queue) newSkipValue(item *mempool.Item) (*skiplist.SkipValue, error ...@@ -36,7 +37,8 @@ func (cache *Queue) newSkipValue(item *mempool.Item) (*skiplist.SkipValue, error
return nil, err return nil, err
} }
size := len(buf.Bytes()) 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 是否存在 // Exist 是否存在
...@@ -122,3 +124,26 @@ func (cache *Queue) Walk(count int, cb func(value *mempool.Item) bool) { ...@@ -122,3 +124,26 @@ func (cache *Queue) Walk(count int, cb func(value *mempool.Item) bool) {
return i != count 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 package score
import ( import (
"testing"
"github.com/33cn/chain33/common" "github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/address" "github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/common/crypto" "github.com/33cn/chain33/common/crypto"
...@@ -10,6 +8,8 @@ import ( ...@@ -10,6 +8,8 @@ import (
drivers "github.com/33cn/chain33/system/mempool" drivers "github.com/33cn/chain33/system/mempool"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"testing"
"time"
) )
var ( var (
...@@ -21,11 +21,11 @@ var ( ...@@ -21,11 +21,11 @@ var (
amount = int64(1e8) amount = int64(1e8)
v = &cty.CoinsAction_Transfer{Transfer: &types.AssetsTransfer{Amount: amount}} v = &cty.CoinsAction_Transfer{Transfer: &types.AssetsTransfer{Amount: amount}}
transfer = &cty.CoinsAction{Value: v, Ty: cty.CoinsActionTransfer} transfer = &cty.CoinsAction{Value: v, Ty: cty.CoinsActionTransfer}
tx1 = &types.Transaction{Execer: []byte("coins"), Payload: types.Encode(transfer), Fee: 1000000, Expire: 1, 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: 1000000, Expire: 2, 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: 1000000, Expire: 3, 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: 2000000, Expire: 4, 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: 1000000, Expire: 5, 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()} item1 = &drivers.Item{Value: tx1, Priority: tx1.Fee, EnterTime: types.Now().Unix()}
item2 = &drivers.Item{Value: tx2, Priority: tx2.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} item3 = &drivers.Item{Value: tx3, Priority: tx3.Fee, EnterTime: types.Now().Unix() - 1000}
...@@ -113,9 +113,9 @@ func TestTimeCompetition(t *testing.T) { ...@@ -113,9 +113,9 @@ func TestTimeCompetition(t *testing.T) {
func TestPriceCompetition(t *testing.T) { func TestPriceCompetition(t *testing.T) {
cache := initEnv(1) cache := initEnv(1)
cache.Push(item1) cache.Push(item3)
cache.Push(item4) 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()))) assert.Equal(t, true, cache.Exist(string(item4.Value.Hash())))
} }
...@@ -149,3 +149,19 @@ func TestQueueDirection(t *testing.T) { ...@@ -149,3 +149,19 @@ func TestQueueDirection(t *testing.T) {
assert.Equal(t, 5, i) assert.Equal(t, 5, i)
assert.Equal(t, true, lastScore == cache.txList.GetIterator().Last().Score) 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 ...@@ -75,7 +75,7 @@ poolCacheSize=10240
[mempool.sub.score] [mempool.sub.score]
poolCacheSize=10240 poolCacheSize=10240
timeParam=1 #时间占价格比例 timeParam=1 #时间占价格比例
priceConstant=1544 #手续费相对于时间的一个合适的常量,取当前unxi时间戳前四位数,排队时手续费高1e-5的分数~=快1s的分数 priceConstant=3 #手续费相对于时间的一个的常量,排队时手续费高1e3的分数~=快1h的分数
pricePower=1 #常量比例 pricePower=1 #常量比例
[mempool.sub.price] [mempool.sub.price]
......
...@@ -14,6 +14,7 @@ type subConfig struct { ...@@ -14,6 +14,7 @@ type subConfig struct {
TimeParam int64 `json:"timeParam"` TimeParam int64 `json:"timeParam"`
PriceConstant int64 `json:"priceConstant"` PriceConstant int64 `json:"priceConstant"`
PricePower int64 `json:"pricePower"` PricePower int64 `json:"pricePower"`
ProperFee int64 `json:"properFee"`
} }
func init() { func init() {
...@@ -28,6 +29,9 @@ func New(cfg *types.Mempool, sub []byte) queue.Module { ...@@ -28,6 +29,9 @@ func New(cfg *types.Mempool, sub []byte) queue.Module {
if subcfg.PoolCacheSize == 0 { if subcfg.PoolCacheSize == 0 {
subcfg.PoolCacheSize = cfg.PoolCacheSize subcfg.PoolCacheSize = cfg.PoolCacheSize
} }
if subcfg.ProperFee == 0 {
subcfg.ProperFee = cfg.MinTxFee
}
c.SetQueueCache(NewQueue(subcfg)) c.SetQueueCache(NewQueue(subcfg))
return c return c
} }
...@@ -47,6 +47,8 @@ func (m *mockMempool) SetQueueClient(q queue.Queue) { ...@@ -47,6 +47,8 @@ func (m *mockMempool) SetQueueClient(q queue.Queue) {
msg.Reply(client.NewMessage(mempoolKey, types.EventReplyTxList, &types.ReplyTxList{})) msg.Reply(client.NewMessage(mempoolKey, types.EventReplyTxList, &types.ReplyTxList{}))
case types.EventGetLastMempool: case types.EventGetLastMempool:
msg.Reply(client.NewMessage(mempoolKey, types.EventReplyTxList, &types.ReplyTxList{})) msg.Reply(client.NewMessage(mempoolKey, types.EventReplyTxList, &types.ReplyTxList{}))
case types.EventGetProperFee:
msg.Reply(client.NewMessage(mempoolKey, types.EventReplyProperFee, &types.ReplyProperFee{}))
default: default:
msg.ReplyErr("Do not support", types.ErrNotSupport) msg.ReplyErr("Do not support", types.ErrNotSupport)
} }
......
...@@ -453,6 +453,29 @@ func (_m *QueueProtocolAPI) GetMempool() (*types.ReplyTxList, error) { ...@@ -453,6 +453,29 @@ func (_m *QueueProtocolAPI) GetMempool() (*types.ReplyTxList, error) {
return r0, r1 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: // GetNetInfo provides a mock function with given fields:
func (_m *QueueProtocolAPI) GetNetInfo() (*types.NodeNetInfo, error) { func (_m *QueueProtocolAPI) GetNetInfo() (*types.NodeNetInfo, error) {
ret := _m.Called() ret := _m.Called()
......
...@@ -468,6 +468,19 @@ func (q *QueueProtocol) GetLastMempool() (*types.ReplyTxList, error) { ...@@ -468,6 +468,19 @@ func (q *QueueProtocol) GetLastMempool() (*types.ReplyTxList, error) {
return nil, types.ErrTypeAsset 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 // GetBlockOverview get block head detil by hash
func (q *QueueProtocol) GetBlockOverview(param *types.ReqHash) (*types.BlockOverview, error) { func (q *QueueProtocol) GetBlockOverview(param *types.ReqHash) (*types.BlockOverview, error) {
if param == nil { if param == nil {
......
...@@ -79,6 +79,7 @@ func TestQueueProtocol(t *testing.T) { ...@@ -79,6 +79,7 @@ func TestQueueProtocol(t *testing.T) {
testPeerInfo(t, api) testPeerInfo(t, api)
testGetHeaders(t, api) testGetHeaders(t, api)
testGetLastMempool(t, api) testGetLastMempool(t, api)
testGetProperFee(t, api)
testGetBlockOverview(t, api) testGetBlockOverview(t, api)
testGetAddrOverview(t, api) testGetAddrOverview(t, api)
testGetBlockHash(t, api) testGetBlockHash(t, api)
...@@ -341,6 +342,13 @@ func testGetLastMempool(t *testing.T, api client.QueueProtocolAPI) { ...@@ -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) { func testGetHeaders(t *testing.T, api client.QueueProtocolAPI) {
_, err := api.GetHeaders(&types.ReqBlocks{}) _, err := api.GetHeaders(&types.ReqBlocks{})
if err != nil { if err != nil {
...@@ -627,6 +635,7 @@ func TestJsonRPC(t *testing.T) { ...@@ -627,6 +635,7 @@ func TestJsonRPC(t *testing.T) {
testGetLastHeaderJsonRPC(t, &jrpc) testGetLastHeaderJsonRPC(t, &jrpc)
testGetMempoolJsonRPC(t, &jrpc) testGetMempoolJsonRPC(t, &jrpc)
testGetLastMemPoolJsonRPC(t, &jrpc) testGetLastMemPoolJsonRPC(t, &jrpc)
testGetProperFeeJsonRPC(t, &jrpc)
testGenSeedsonRPC(t, &jrpc) testGenSeedsonRPC(t, &jrpc)
testGetPeerInfoJsonRPC(t, &jrpc) testGetPeerInfoJsonRPC(t, &jrpc)
testIsNtpClockSyncJsonRPC(t, &jrpc) testIsNtpClockSyncJsonRPC(t, &jrpc)
...@@ -723,6 +732,15 @@ func testGetLastMemPoolJsonRPC(t *testing.T, rpc *mockJRPCSystem) { ...@@ -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) { func testGetMempoolJsonRPC(t *testing.T, rpc *mockJRPCSystem) {
var res rpctypes.ReplyTxList var res rpctypes.ReplyTxList
err := rpc.newRpcCtx("Chain33.GetMempool", err := rpc.newRpcCtx("Chain33.GetMempool",
...@@ -820,6 +838,7 @@ func TestGRPC(t *testing.T) { ...@@ -820,6 +838,7 @@ func TestGRPC(t *testing.T) {
testUnLockGRPC(t, &grpcMock) testUnLockGRPC(t, &grpcMock)
testGetPeerInfoGRPC(t, &grpcMock) testGetPeerInfoGRPC(t, &grpcMock)
testGetLastMemPoolGRPC(t, &grpcMock) testGetLastMemPoolGRPC(t, &grpcMock)
testGetProperFeeGRPC(t, &grpcMock)
testGetWalletStatusGRPC(t, &grpcMock) testGetWalletStatusGRPC(t, &grpcMock)
testGetBlockOverviewGRPC(t, &grpcMock) testGetBlockOverviewGRPC(t, &grpcMock)
testGetAddrOverviewGRPC(t, &grpcMock) testGetAddrOverviewGRPC(t, &grpcMock)
...@@ -969,6 +988,14 @@ func testGetLastMemPoolGRPC(t *testing.T, rpc *mockGRPCSystem) { ...@@ -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) { func testGetPeerInfoGRPC(t *testing.T, rpc *mockGRPCSystem) {
var res types.PeerList var res types.PeerList
err := rpc.newRpcCtx("GetPeerInfo", &types.ReqNil{}, &res) err := rpc.newRpcCtx("GetPeerInfo", &types.ReqNil{}, &res)
......
...@@ -24,6 +24,8 @@ type QueueProtocolAPI interface { ...@@ -24,6 +24,8 @@ type QueueProtocolAPI interface {
GetMempool() (*types.ReplyTxList, error) GetMempool() (*types.ReplyTxList, error)
// types.EventGetLastMempool // types.EventGetLastMempool
GetLastMempool() (*types.ReplyTxList, error) GetLastMempool() (*types.ReplyTxList, error)
// types.EventGetProperFee
GetProperFee() (*types.ReplyProperFee, error)
// +++++++++++++++ execs interfaces begin // +++++++++++++++ execs interfaces begin
// types.EventBlockChainQuery // types.EventBlockChainQuery
Query(driver, funcname string, param types.Message) (types.Message, error) Query(driver, funcname string, param types.Message) (types.Message, error)
......
...@@ -225,6 +225,12 @@ func (c *GrpcCtx) Run() (err error) { ...@@ -225,6 +225,12 @@ func (c *GrpcCtx) Run() (err error) {
*c.Res.(*types.ReplyTxList) = *reply *c.Res.(*types.ReplyTxList) = *reply
} }
errRet = err 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": case "GetWalletStatus":
reply, err := rpc.GetWalletStatus(context.Background(), c.Params.(*types.ReqNil)) reply, err := rpc.GetWalletStatus(context.Background(), c.Params.(*types.ReqNil))
if err == nil { if err == nil {
......
...@@ -208,6 +208,11 @@ func (g *Grpc) GetLastMemPool(ctx context.Context, in *pb.ReqNil) (*pb.ReplyTxLi ...@@ -208,6 +208,11 @@ func (g *Grpc) GetLastMemPool(ctx context.Context, in *pb.ReqNil) (*pb.ReplyTxLi
return g.cli.GetLastMempool() 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 get block overview
// GetBlockOverview(parm *types.ReqHash) (*types.BlockOverview, error) //add by hyb // GetBlockOverview(parm *types.ReqHash) (*types.BlockOverview, error) //add by hyb
func (g *Grpc) GetBlockOverview(ctx context.Context, in *pb.ReqHash) (*pb.BlockOverview, error) { func (g *Grpc) GetBlockOverview(ctx context.Context, in *pb.ReqHash) (*pb.BlockOverview, error) {
......
...@@ -202,6 +202,18 @@ func TestGetLastMemPool(t *testing.T) { ...@@ -202,6 +202,18 @@ func TestGetLastMemPool(t *testing.T) {
testGetLastMemPoolOK(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) { //func (g *Grpc) QueryChain(ctx context.Context, in *pb.Query) (*pb.Reply, error) {
// if !g.checkWhitlist(ctx) { // if !g.checkWhitlist(ctx) {
// return nil, fmt.Errorf("reject") // return nil, fmt.Errorf("reject")
......
...@@ -616,6 +616,18 @@ func (c *Chain33) GetLastMemPool(in types.ReqNil, result *interface{}) error { ...@@ -616,6 +616,18 @@ func (c *Chain33) GetLastMemPool(in types.ReqNil, result *interface{}) error {
return nil 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 get overview of block
// GetBlockOverview(parm *types.ReqHash) (*types.BlockOverview, error) // GetBlockOverview(parm *types.ReqHash) (*types.BlockOverview, error)
func (c *Chain33) GetBlockOverview(in rpctypes.QueryParm, result *interface{}) error { func (c *Chain33) GetBlockOverview(in rpctypes.QueryParm, result *interface{}) error {
......
...@@ -1019,6 +1019,23 @@ func TestChain33_GetLastMemPool(t *testing.T) { ...@@ -1019,6 +1019,23 @@ func TestChain33_GetLastMemPool(t *testing.T) {
mock.AssertExpectationsForObjects(t, api) 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) { func TestChain33_GetBlockOverview(t *testing.T) {
api := new(mocks.QueueProtocolAPI) api := new(mocks.QueueProtocolAPI)
testChain33 := newTestChain33(api) testChain33 := newTestChain33(api)
......
...@@ -173,6 +173,11 @@ type ReplyTxList struct { ...@@ -173,6 +173,11 @@ type ReplyTxList struct {
Txs []*Transaction `json:"txs"` Txs []*Transaction `json:"txs"`
} }
// ReplyTxList reply tx list
type ReplyProperFee struct {
ProperFee int64 `json:"properFee"`
}
// ReplyHash reply hash string json // ReplyHash reply hash string json
type ReplyHash struct { type ReplyHash struct {
Hash string `json:"hash"` Hash string `json:"hash"`
......
...@@ -22,6 +22,7 @@ func MempoolCmd() *cobra.Command { ...@@ -22,6 +22,7 @@ func MempoolCmd() *cobra.Command {
cmd.AddCommand( cmd.AddCommand(
GetMempoolCmd(), GetMempoolCmd(),
GetLastMempoolCmd(), GetLastMempoolCmd(),
GetProperFeeCmd(),
) )
return cmd return cmd
...@@ -80,3 +81,21 @@ func parselastMempoolTxsRes(arg interface{}) (interface{}, error) { ...@@ -80,3 +81,21 @@ func parselastMempoolTxsRes(arg interface{}) (interface{}, error) {
} }
return result, nil 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 { ...@@ -16,6 +16,7 @@ type QueueCache interface {
Remove(hash string) error Remove(hash string) error
Size() int Size() int
Walk(count int, cb func(tx *Item) bool) Walk(count int, cb func(tx *Item) bool)
GetProperFee() int64
} }
// Item 为Mempool中包装交易的数据结构 // Item 为Mempool中包装交易的数据结构
......
...@@ -87,6 +87,9 @@ func (mem *Mempool) eventProcess() { ...@@ -87,6 +87,9 @@ func (mem *Mempool) eventProcess() {
case types.EventGetAddrTxs: case types.EventGetAddrTxs:
// 获取mempool中对应账户(组)所有交易 // 获取mempool中对应账户(组)所有交易
mem.eventGetAddrTxs(msg) mem.eventGetAddrTxs(msg)
case types.EventGetProperFee:
// 获取对应排队策略中合适的手续费
mem.eventGetProperFee(msg)
default: default:
} }
mlog.Debug("mempool", "cost", types.Since(beg), "msg", types.GetEventName(int(msg.Ty))) mlog.Debug("mempool", "cost", types.Since(beg), "msg", types.GetEventName(int(msg.Ty)))
...@@ -186,6 +189,13 @@ func (mem *Mempool) eventGetAddrTxs(msg *queue.Message) { ...@@ -186,6 +189,13 @@ func (mem *Mempool) eventGetAddrTxs(msg *queue.Message) {
msg.Reply(mem.client.NewMessage("", types.EventReplyAddrTxs, txlist)) 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 { func (mem *Mempool) checkSign(data *queue.Message) *queue.Message {
tx, ok := data.GetData().(types.TxGroup) tx, ok := data.GetData().(types.TxGroup)
if ok && tx.CheckSign() { if ok && tx.CheckSign() {
......
...@@ -124,8 +124,9 @@ func initEnv3() (queue.Queue, queue.Module, queue.Module, *Mempool) { ...@@ -124,8 +124,9 @@ func initEnv3() (queue.Queue, queue.Module, queue.Module, *Mempool) {
types.SetMinFee(0) types.SetMinFee(0)
s := store.New(cfg.Store, sub.Store) s := store.New(cfg.Store, sub.Store)
s.SetQueueClient(q.Client()) s.SetQueueClient(q.Client())
subConfig := SubConfig{cfg.Mempool.PoolCacheSize, cfg.Mempool.MinTxFee}
mem := NewMempool(cfg.Mempool) mem := NewMempool(cfg.Mempool)
mem.SetQueueCache(NewSimpleQueue(int(cfg.Mempool.PoolCacheSize))) mem.SetQueueCache(NewSimpleQueue(subConfig))
mem.SetQueueClient(q.Client()) mem.SetQueueClient(q.Client())
mem.Wait() mem.Wait()
return q, chain, s, mem return q, chain, s, mem
...@@ -138,8 +139,9 @@ func initEnv2(size int) (queue.Queue, *Mempool) { ...@@ -138,8 +139,9 @@ func initEnv2(size int) (queue.Queue, *Mempool) {
blockchainProcess(q) blockchainProcess(q)
execProcess(q) execProcess(q)
cfg.Mempool.PoolCacheSize = int64(size) cfg.Mempool.PoolCacheSize = int64(size)
subConfig := SubConfig{cfg.Mempool.PoolCacheSize, cfg.Mempool.MinTxFee}
mem := NewMempool(cfg.Mempool) mem := NewMempool(cfg.Mempool)
mem.SetQueueCache(NewSimpleQueue(size)) mem.SetQueueCache(NewSimpleQueue(subConfig))
mem.SetQueueClient(q.Client()) mem.SetQueueClient(q.Client())
mem.setSync(true) mem.setSync(true)
mem.SetMinFee(0) mem.SetMinFee(0)
...@@ -157,8 +159,9 @@ func initEnv(size int) (queue.Queue, *Mempool) { ...@@ -157,8 +159,9 @@ func initEnv(size int) (queue.Queue, *Mempool) {
blockchainProcess(q) blockchainProcess(q)
execProcess(q) execProcess(q)
cfg.Mempool.PoolCacheSize = int64(size) cfg.Mempool.PoolCacheSize = int64(size)
subConfig := SubConfig{cfg.Mempool.PoolCacheSize, cfg.Mempool.MinTxFee}
mem := NewMempool(cfg.Mempool) mem := NewMempool(cfg.Mempool)
mem.SetQueueCache(NewSimpleQueue(size)) mem.SetQueueCache(NewSimpleQueue(subConfig))
mem.SetQueueClient(q.Client()) mem.SetQueueClient(q.Client())
mem.setSync(true) mem.setSync(true)
mem.SetMinFee(types.GInt("MinFee")) mem.SetMinFee(types.GInt("MinFee"))
...@@ -567,6 +570,37 @@ func TestGetLatestTx(t *testing.T) { ...@@ -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) { func TestCheckLowFee(t *testing.T) {
q, mem := initEnv(0) q, mem := initEnv(0)
defer q.Close() defer q.Close()
......
...@@ -9,17 +9,22 @@ import ( ...@@ -9,17 +9,22 @@ import (
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
) )
type SubConfig struct {
PoolCacheSize int64 `json:"poolCacheSize"`
ProperFee int64 `json:"properFee"`
}
//SimpleQueue 简单队列模式(默认提供一个队列,便于测试) //SimpleQueue 简单队列模式(默认提供一个队列,便于测试)
type SimpleQueue struct { type SimpleQueue struct {
txList *listmap.ListMap txList *listmap.ListMap
maxsize int subConfig SubConfig
} }
//NewSimpleQueue 创建队列 //NewSimpleQueue 创建队列
func NewSimpleQueue(cacheSize int) *SimpleQueue { func NewSimpleQueue(subConfig SubConfig) *SimpleQueue {
return &SimpleQueue{ return &SimpleQueue{
txList: listmap.New(), txList: listmap.New(),
maxsize: cacheSize, subConfig: subConfig,
} }
} }
...@@ -43,7 +48,7 @@ func (cache *SimpleQueue) Push(tx *Item) error { ...@@ -43,7 +48,7 @@ func (cache *SimpleQueue) Push(tx *Item) error {
if cache.Exist(string(hash)) { if cache.Exist(string(hash)) {
return types.ErrTxExist return types.ErrTxExist
} }
if cache.txList.Size() >= cache.maxsize { if cache.txList.Size() >= int(cache.subConfig.PoolCacheSize) {
return types.ErrMemFull return types.ErrMemFull
} }
cache.txList.Push(string(hash), tx) cache.txList.Push(string(hash), tx)
...@@ -72,3 +77,8 @@ func (cache *SimpleQueue) Walk(count int, cb func(value *Item) bool) { ...@@ -72,3 +77,8 @@ func (cache *SimpleQueue) Walk(count int, cb func(value *Item) bool) {
return i != count return i != count
}) })
} }
// GetProperFee 获取合适的手续费
func (cache *SimpleQueue) GetProperFee() int64 {
return cache.subConfig.ProperFee
}
...@@ -12,7 +12,8 @@ import ( ...@@ -12,7 +12,8 @@ import (
) )
func TestCache(t *testing.T) { func TestCache(t *testing.T) {
cache := NewSimpleQueue(1) subConfig := SubConfig{1, 100000}
cache := NewSimpleQueue(subConfig)
tx := &types.Transaction{Payload: []byte("123")} tx := &types.Transaction{Payload: []byte("123")}
hash := string(tx.Hash()) hash := string(tx.Hash())
assert.Equal(t, false, cache.Exist(hash)) assert.Equal(t, false, cache.Exist(hash))
...@@ -38,7 +39,8 @@ func TestCache(t *testing.T) { ...@@ -38,7 +39,8 @@ func TestCache(t *testing.T) {
cache.Remove(hash) cache.Remove(hash)
assert.Equal(t, 0, cache.Size()) assert.Equal(t, 0, cache.Size())
//push to item //push to item
cache = NewSimpleQueue(2) subConfig = SubConfig{2, 100000}
cache = NewSimpleQueue(subConfig)
cache.Push(item1) cache.Push(item1)
cache.Push(item2) cache.Push(item2)
assert.Equal(t, 2, cache.Size()) assert.Equal(t, 2, cache.Size())
...@@ -69,4 +71,7 @@ func TestCache(t *testing.T) { ...@@ -69,4 +71,7 @@ func TestCache(t *testing.T) {
return false return false
}) })
assert.Equal(t, 1, i) assert.Equal(t, 1, i)
//test timeline GetProperFee
assert.Equal(t, int64(100000), cache.GetProperFee())
} }
...@@ -14,18 +14,17 @@ func init() { ...@@ -14,18 +14,17 @@ func init() {
drivers.Reg("timeline", New) drivers.Reg("timeline", New)
} }
type subConfig struct {
PoolCacheSize int64 `json:"poolCacheSize"`
}
//New 创建timeline cache 结构的 mempool //New 创建timeline cache 结构的 mempool
func New(cfg *types.Mempool, sub []byte) queue.Module { func New(cfg *types.Mempool, sub []byte) queue.Module {
c := drivers.NewMempool(cfg) c := drivers.NewMempool(cfg)
var subcfg subConfig var subcfg drivers.SubConfig
types.MustDecode(sub, &subcfg) types.MustDecode(sub, &subcfg)
if subcfg.PoolCacheSize == 0 { if subcfg.PoolCacheSize == 0 {
subcfg.PoolCacheSize = cfg.PoolCacheSize 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 return c
} }
...@@ -58,13 +58,13 @@ type Mempool struct { ...@@ -58,13 +58,13 @@ type Mempool struct {
// mempool队列名称,可配,timeline,score,price // mempool队列名称,可配,timeline,score,price
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
// mempool缓存容量大小,默认10240 // 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 // 最小得交易手续费用,这个没有默认值,必填,一般是100000
MinTxFee int64 `protobuf:"varint,2,opt,name=minTxFee" json:"minTxFee,omitempty"` MinTxFee int64 `protobuf:"varint,3,opt,name=minTxFee" json:"minTxFee,omitempty"`
ForceAccept bool `protobuf:"varint,3,opt,name=forceAccept" json:"forceAccept,omitempty"` ForceAccept bool `protobuf:"varint,4,opt,name=forceAccept" json:"forceAccept,omitempty"`
// 每个账户在mempool中得最大交易数量,默认100 // 每个账户在mempool中得最大交易数量,默认100
MaxTxNumPerAccount int64 `protobuf:"varint,4,opt,name=maxTxNumPerAccount" json:"maxTxNumPerAccount,omitempty"` MaxTxNumPerAccount int64 `protobuf:"varint,5,opt,name=maxTxNumPerAccount" json:"maxTxNumPerAccount,omitempty"`
MaxTxLast int64 `protobuf:"varint,4,opt,name=maxTxLast" json:"maxTxLast,omitempty"` MaxTxLast int64 `protobuf:"varint,6,opt,name=maxTxLast" json:"maxTxLast,omitempty"`
} }
// Consensus 配置 // Consensus 配置
......
...@@ -146,6 +146,11 @@ const ( ...@@ -146,6 +146,11 @@ const (
EventLocalRollback = 137 EventLocalRollback = 137
EventLocalNew = 138 EventLocalNew = 138
EventLocalClose = 139 EventLocalClose = 139
//mempool
EventGetProperFee = 140
EventReplyProperFee = 141
//exec //exec
EventBlockChainQuery = 212 EventBlockChainQuery = 212
EventConsensusQuery = 213 EventConsensusQuery = 213
...@@ -290,4 +295,8 @@ var eventName = map[int]string{ ...@@ -290,4 +295,8 @@ var eventName = map[int]string{
EventLocalRollback: "EventLocalRollback", EventLocalRollback: "EventLocalRollback",
EventLocalNew: "EventLocalNew", EventLocalNew: "EventLocalNew",
EventLocalClose: "EventLocalClose", EventLocalClose: "EventLocalClose",
//mempool
EventGetProperFee: "EventGetProperFee",
EventReplyProperFee: "EventReplyProperFee",
} }
...@@ -672,6 +672,36 @@ func (_m *Chain33Client) GetLastHeader(ctx context.Context, in *types.ReqNil, op ...@@ -672,6 +672,36 @@ func (_m *Chain33Client) GetLastHeader(ctx context.Context, in *types.ReqNil, op
return r0, r1 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 // 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) { func (_m *Chain33Client) GetLastMemPool(ctx context.Context, in *types.ReqNil, opts ...grpc.CallOption) (*types.ReplyTxList, error) {
_va := make([]interface{}, len(opts)) _va := make([]interface{}, len(opts))
......
...@@ -76,6 +76,9 @@ service chain33 { ...@@ -76,6 +76,9 @@ service chain33 {
//获取最新的Mempool //获取最新的Mempool
rpc GetLastMemPool(ReqNil) returns (ReplyTxList) {} rpc GetLastMemPool(ReqNil) returns (ReplyTxList) {}
//获取最新的ProperFee
rpc GetProperFee(ReqNil) returns (ReplyProperFee) {}
// 获取钱包状态 // 获取钱包状态
rpc GetWalletStatus(ReqNil) returns (WalletStatus) {} rpc GetWalletStatus(ReqNil) returns (WalletStatus) {}
//区块浏览器接口 //区块浏览器接口
......
...@@ -171,6 +171,10 @@ message ReplyTxList { ...@@ -171,6 +171,10 @@ message ReplyTxList {
repeated Transaction txs = 1; repeated Transaction txs = 1;
} }
message ReplyProperFee {
int64 properFee = 1;
}
message TxHashList { message TxHashList {
repeated bytes hashes = 1; repeated bytes hashes = 1;
int64 count = 2; int64 count = 2;
......
...@@ -6,10 +6,9 @@ package types ...@@ -6,10 +6,9 @@ package types
import ( import (
context "context" context "context"
fmt "fmt" fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto" proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc" grpc "google.golang.org/grpc"
math "math"
) )
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
...@@ -26,73 +25,74 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package ...@@ -26,73 +25,74 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) }
var fileDescriptor_77a6da22d6a3feb1 = []byte{ var fileDescriptor_77a6da22d6a3feb1 = []byte{
// 1052 bytes of a gzipped FileDescriptorProto // 1068 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0xdb, 0x6e, 0xdb, 0x46, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0x6d, 0x6f, 0xdb, 0x36,
0x13, 0xe6, 0xc5, 0xff, 0xdb, 0xf1, 0x46, 0x96, 0xe5, 0xb5, 0x62, 0x24, 0x44, 0x83, 0x00, 0x04, 0x10, 0xd6, 0x87, 0xad, 0x69, 0x58, 0x27, 0x71, 0x98, 0x34, 0x6b, 0x85, 0x15, 0x05, 0x04, 0x0c,
0x8a, 0x16, 0x28, 0x22, 0x25, 0x52, 0xeb, 0x1e, 0x82, 0x16, 0xb0, 0xec, 0x4a, 0x16, 0xaa, 0xa8, 0x1b, 0x30, 0xd4, 0x6e, 0xed, 0x2d, 0x7b, 0x29, 0x36, 0x20, 0x4e, 0x66, 0xc7, 0x58, 0xea, 0xa5,
0x8a, 0xa9, 0xb4, 0x40, 0xef, 0x56, 0xd4, 0x54, 0x26, 0x4c, 0xed, 0xd2, 0xdc, 0xa5, 0x45, 0x3d, 0x91, 0xbb, 0x01, 0xfb, 0x46, 0xcb, 0x37, 0x47, 0x88, 0x4c, 0x2a, 0x24, 0x15, 0xcb, 0xbf, 0x66,
0x71, 0x5f, 0xa3, 0xd8, 0x25, 0x97, 0x67, 0xd9, 0xee, 0x9d, 0x76, 0x66, 0xbe, 0x39, 0x68, 0xbe, 0x7f, 0x75, 0x20, 0x25, 0xea, 0xdd, 0x49, 0xf6, 0x4d, 0xbc, 0xbb, 0xe7, 0x5e, 0xc4, 0xe7, 0xee,
0x99, 0x21, 0x3a, 0x08, 0x7c, 0xa7, 0xe3, 0x07, 0x4c, 0x30, 0xfc, 0x7f, 0xb1, 0xf5, 0x81, 0x9b, 0x88, 0xb6, 0x79, 0xe8, 0x75, 0x42, 0xce, 0x24, 0xc3, 0x9f, 0xcb, 0x75, 0x08, 0xc2, 0x6e, 0x79,
0x0d, 0x87, 0xad, 0xd7, 0x8c, 0xc6, 0x42, 0xf3, 0x58, 0x04, 0x84, 0x72, 0xe2, 0x08, 0x37, 0x15, 0x6c, 0xb9, 0x64, 0x34, 0x11, 0xda, 0xfb, 0x92, 0x13, 0x2a, 0x88, 0x27, 0xfd, 0x4c, 0xd4, 0x9e,
0xb5, 0x16, 0x1e, 0x73, 0x6e, 0x9d, 0x1b, 0xe2, 0x6a, 0x49, 0x63, 0x43, 0x3c, 0x0f, 0x44, 0xf2, 0x05, 0xcc, 0xbb, 0xf1, 0xae, 0x89, 0x6f, 0x24, 0xad, 0x15, 0x09, 0x02, 0x90, 0xe9, 0x69, 0x3b,
0x3a, 0xf0, 0x7b, 0x7e, 0xf2, 0xf3, 0x90, 0x38, 0x0e, 0x0b, 0xa9, 0xd6, 0x34, 0x21, 0x02, 0x27, 0xec, 0x85, 0xe9, 0xe7, 0x0e, 0xf1, 0x3c, 0x16, 0x51, 0xa3, 0xd9, 0x85, 0x18, 0xbc, 0x48, 0x32,
0x14, 0x2c, 0x88, 0xdf, 0xbd, 0x7f, 0x4e, 0xd1, 0xbe, 0xf2, 0xd3, 0xef, 0xe3, 0xb7, 0xe8, 0x60, 0x9e, 0x9c, 0x7b, 0xff, 0x7e, 0x81, 0xb6, 0xb4, 0x9f, 0x7e, 0x1f, 0xbf, 0x41, 0xdb, 0x23, 0x90,
0x04, 0x62, 0x20, 0x5d, 0x73, 0xdc, 0xea, 0xa8, 0x5c, 0x3a, 0xd7, 0x70, 0x17, 0x4b, 0xcc, 0x46, 0x03, 0xe5, 0x5a, 0xe0, 0x76, 0x47, 0xe7, 0xd2, 0xb9, 0x82, 0xdb, 0x44, 0x62, 0xb7, 0x32, 0x49,
0x2a, 0xf1, 0xbd, 0xad, 0x65, 0xe0, 0x2e, 0x3a, 0x1c, 0x81, 0x98, 0x10, 0x2e, 0xae, 0x80, 0x2c, 0x18, 0xac, 0x1d, 0x0b, 0x77, 0xd1, 0xce, 0x08, 0xe4, 0x05, 0x11, 0xf2, 0x1c, 0xc8, 0x1c, 0x38,
0x21, 0xc0, 0x87, 0x19, 0x64, 0xea, 0x7a, 0xa6, 0x7e, 0xc6, 0x5a, 0xcb, 0xc0, 0x3f, 0xa1, 0xf6, 0xde, 0xc9, 0x21, 0x13, 0x3f, 0xb0, 0xcd, 0x31, 0xd1, 0x3a, 0x16, 0xfe, 0x19, 0x1d, 0x9e, 0x72,
0x45, 0x00, 0x44, 0xc0, 0x35, 0xd9, 0xcc, 0xb3, 0x9a, 0xf0, 0x51, 0x62, 0x18, 0x2b, 0xe7, 0x91, 0x20, 0x12, 0xae, 0xc8, 0x6a, 0x9a, 0xd7, 0x84, 0xf7, 0x52, 0xc3, 0x44, 0x39, 0x8d, 0x6d, 0x23,
0xa9, 0x05, 0x9f, 0x29, 0x77, 0x57, 0x74, 0x1e, 0x59, 0x06, 0xbe, 0x44, 0xad, 0x0c, 0x1b, 0x8d, 0xf8, 0x44, 0x85, 0xbf, 0xa0, 0xd3, 0xd8, 0xb1, 0xf0, 0x19, 0x6a, 0xe7, 0xd8, 0x78, 0xc4, 0x59,
0x02, 0x16, 0xfa, 0xf8, 0x75, 0x11, 0x97, 0x79, 0x54, 0xea, 0x3a, 0x2f, 0xdf, 0x21, 0x6c, 0x03, 0x14, 0xe2, 0x57, 0x65, 0x5c, 0xee, 0x51, 0xab, 0x9b, 0xbc, 0x7c, 0x8f, 0xb0, 0x0b, 0x74, 0xbe,
0x5d, 0xee, 0x88, 0x6f, 0xbb, 0x2b, 0x0a, 0xcb, 0x79, 0x54, 0xa9, 0xf4, 0x17, 0xd4, 0xfa, 0x14, 0x21, 0xbe, 0xeb, 0x2f, 0x28, 0xcc, 0xa7, 0x71, 0xad, 0xd2, 0x5f, 0x51, 0xfb, 0x63, 0x04, 0x7c,
0x42, 0xb0, 0xcd, 0x83, 0x9a, 0x59, 0xb1, 0x57, 0x84, 0xdf, 0x98, 0x2f, 0x93, 0x77, 0xce, 0xe6, 0x5d, 0x04, 0xed, 0xe6, 0xc5, 0x9e, 0x13, 0x71, 0x6d, 0xbf, 0x48, 0xcf, 0x05, 0x9b, 0x33, 0x90,
0x12, 0x04, 0x71, 0x3d, 0x15, 0xf6, 0x48, 0x86, 0xcd, 0xc3, 0x71, 0xd5, 0xbc, 0x12, 0xf6, 0x67, 0xc4, 0x0f, 0x74, 0xd8, 0x3d, 0x15, 0xb6, 0x08, 0xc7, 0x75, 0xf3, 0x5a, 0xd8, 0x5f, 0xd0, 0xe1,
0xd4, 0x1e, 0x81, 0xc8, 0x59, 0x0c, 0xb6, 0xe7, 0xcb, 0x65, 0x90, 0x0f, 0x2d, 0xdf, 0xe6, 0x49, 0x08, 0x64, 0xc1, 0x62, 0xb0, 0x3e, 0x99, 0xcf, 0x79, 0x31, 0xb4, 0x3a, 0xdb, 0x07, 0x45, 0xdc,
0x1e, 0x37, 0x8f, 0xc6, 0xf4, 0x6f, 0xc6, 0x2d, 0x03, 0x8f, 0xd0, 0x69, 0x19, 0x2e, 0x33, 0x85, 0x34, 0x1e, 0xd3, 0x7f, 0x98, 0x70, 0x2c, 0x3c, 0x42, 0x47, 0x55, 0xb8, 0xca, 0x14, 0x4a, 0x77,
0x42, 0x6f, 0x63, 0x89, 0xf9, 0x6a, 0x57, 0xf6, 0xd2, 0xd1, 0x7b, 0x84, 0x46, 0x20, 0x3e, 0xc2, 0x9b, 0x48, 0xec, 0x97, 0x9b, 0xb2, 0x57, 0x8e, 0xde, 0x21, 0x34, 0x02, 0xf9, 0x01, 0x96, 0x97,
0x7a, 0xc6, 0x98, 0x57, 0xee, 0x32, 0x2e, 0x06, 0x9f, 0xb8, 0x5c, 0xa8, 0x8a, 0x9f, 0x8f, 0x40, 0x8c, 0x05, 0xd5, 0x5b, 0xc6, 0xe5, 0xe0, 0x17, 0xbe, 0x90, 0xba, 0xe2, 0x67, 0x23, 0x90, 0x27,
0x9c, 0xc7, 0xd4, 0xe3, 0x65, 0xcc, 0x8b, 0xe4, 0xf9, 0xa7, 0xe2, 0xac, 0xb6, 0x52, 0x0c, 0x41, 0x09, 0xf5, 0x44, 0x15, 0xf3, 0x3c, 0x3d, 0xfe, 0xa5, 0x39, 0x6b, 0xac, 0x34, 0x43, 0xd0, 0x04,
0x53, 0xd8, 0x24, 0x02, 0xdc, 0xce, 0xa1, 0x52, 0xa9, 0xd9, 0xae, 0x03, 0x5b, 0x06, 0xbe, 0x46, 0x56, 0xa9, 0x00, 0x1f, 0x16, 0x50, 0x99, 0xd4, 0x3e, 0x6c, 0x02, 0x3b, 0x16, 0xbe, 0x42, 0xcf,
0x2f, 0x62, 0x51, 0xae, 0x06, 0x99, 0x0d, 0x7e, 0x93, 0xb9, 0xa9, 0x35, 0x30, 0x4f, 0x0b, 0x1e, 0x13, 0x51, 0xa1, 0x06, 0x95, 0x0d, 0x7e, 0x9d, 0xbb, 0x69, 0x34, 0xb0, 0x8f, 0x4a, 0x1e, 0xa7,
0xe7, 0x51, 0x56, 0xf9, 0x10, 0x1d, 0x8e, 0xd7, 0x3e, 0x0b, 0xc4, 0x2c, 0x70, 0xef, 0x6f, 0x61, 0x71, 0x5e, 0xf9, 0x10, 0xed, 0x8c, 0x97, 0x21, 0xe3, 0xf2, 0x92, 0xfb, 0x77, 0x37, 0xb0, 0xce,
0x9b, 0x52, 0x2e, 0xf5, 0x55, 0x50, 0xef, 0xcc, 0x6d, 0x80, 0x0e, 0x15, 0x01, 0x98, 0xec, 0x17, 0x28, 0x97, 0xf9, 0x2a, 0xa9, 0x37, 0xe6, 0x36, 0x40, 0x3b, 0x9a, 0x00, 0x4c, 0xdd, 0x17, 0x08,
0x70, 0x5e, 0xf5, 0x53, 0x50, 0x9b, 0xad, 0xfc, 0x9f, 0x2a, 0x5b, 0x64, 0x19, 0xb8, 0x87, 0x9e, 0x51, 0xf7, 0x53, 0x52, 0xdb, 0xed, 0xe2, 0x4f, 0x55, 0x57, 0xe4, 0x58, 0xb8, 0x87, 0x9e, 0xba,
0xd9, 0x32, 0xbb, 0x21, 0x00, 0x3e, 0xad, 0xc2, 0xc5, 0x10, 0xa0, 0xc2, 0xa0, 0x0f, 0x68, 0xdf, 0x2a, 0xbb, 0x21, 0x00, 0x3e, 0xaa, 0xc3, 0xe5, 0x10, 0xa0, 0xc6, 0xa0, 0xf7, 0x68, 0xcb, 0x55,
0x96, 0x23, 0xba, 0xf0, 0xf0, 0xcb, 0x1a, 0xc8, 0x84, 0x2c, 0xc0, 0x7b, 0x20, 0xe9, 0xc6, 0x47, 0x2d, 0x3a, 0x0b, 0xf0, 0x8b, 0x06, 0xc8, 0x05, 0x99, 0x41, 0x70, 0x4f, 0xd2, 0xad, 0x0f, 0xc0,
0x08, 0x56, 0x30, 0x20, 0x1e, 0xa1, 0x0e, 0xe0, 0x2f, 0xca, 0x1e, 0xf2, 0xda, 0x22, 0x0f, 0x62, 0x17, 0x30, 0x20, 0x01, 0xa1, 0x1e, 0xe0, 0x2f, 0xab, 0x1e, 0x8a, 0xda, 0x32, 0x0f, 0x12, 0x56,
0x56, 0x59, 0x06, 0x3e, 0x43, 0x07, 0x36, 0x88, 0x19, 0xe1, 0x7c, 0xb3, 0xc4, 0xaf, 0x6a, 0x52, 0x39, 0x16, 0x3e, 0x46, 0xdb, 0x2e, 0xc8, 0x4b, 0x22, 0xc4, 0x6a, 0x8e, 0x5f, 0x36, 0xa4, 0x90,
0x88, 0x55, 0x95, 0xc4, 0xbf, 0x44, 0xff, 0x9b, 0x30, 0xe7, 0xb6, 0x4c, 0x9c, 0xb2, 0xd9, 0x5b, 0xa8, 0x6a, 0x89, 0x7f, 0x85, 0x3e, 0xbb, 0x60, 0xde, 0x4d, 0x95, 0x38, 0x55, 0xb3, 0x37, 0xe8,
0xb4, 0xf7, 0x99, 0x2a, 0xc3, 0x93, 0x42, 0x11, 0xb1, 0xb0, 0x66, 0x63, 0x49, 0x56, 0xce, 0x00, 0xc9, 0x27, 0xaa, 0x0d, 0x0f, 0x4a, 0x45, 0x24, 0xc2, 0x86, 0x89, 0xa5, 0x58, 0x79, 0x09, 0xc0,
0x02, 0x39, 0x23, 0x65, 0xe7, 0x7a, 0x0d, 0x48, 0x7d, 0x4a, 0xe3, 0x66, 0xb2, 0xe2, 0xfe, 0x13, 0x55, 0x8f, 0x54, 0x9d, 0x9b, 0x31, 0xa0, 0xf4, 0x19, 0x8d, 0x77, 0xd3, 0x11, 0xf7, 0xbf, 0xd8,
0xfb, 0xbf, 0x47, 0x47, 0x23, 0x10, 0x49, 0x8d, 0x82, 0x88, 0xb0, 0x32, 0x01, 0xc5, 0x74, 0x63, 0x7f, 0x8c, 0x5a, 0x2a, 0x0e, 0x67, 0x21, 0x70, 0x75, 0x5d, 0x1b, 0xe8, 0xaf, 0x41, 0x99, 0x95,
0x1b, 0xc5, 0xff, 0x96, 0xde, 0xc0, 0xbf, 0xdf, 0x43, 0x70, 0xef, 0xc2, 0xa6, 0xb2, 0x68, 0x74, 0x63, 0xe1, 0x1f, 0xd0, 0xde, 0x08, 0x64, 0xfa, 0x6f, 0x24, 0x91, 0x51, 0xad, 0x73, 0xca, 0x65,
0xbb, 0x0a, 0x56, 0x96, 0x81, 0x7f, 0x50, 0x41, 0x25, 0x83, 0xea, 0xa0, 0x85, 0x45, 0x91, 0x37, 0x26, 0x36, 0xba, 0x6f, 0xda, 0x66, 0x72, 0xff, 0x71, 0x07, 0xfc, 0xce, 0x87, 0x55, 0x6d, 0x40,
0x52, 0xf3, 0xdd, 0xd0, 0x51, 0x65, 0x84, 0x7c, 0xae, 0x63, 0x2a, 0x6a, 0xc9, 0xf8, 0x1e, 0xed, 0x99, 0x6b, 0x2e, 0x59, 0x39, 0x16, 0xfe, 0x51, 0x07, 0x55, 0xcc, 0x6b, 0x82, 0x96, 0x06, 0x4c,
0x8f, 0x80, 0xda, 0x00, 0xcb, 0x74, 0x93, 0x25, 0xef, 0x09, 0xa1, 0xab, 0x22, 0x44, 0x4a, 0x35, 0xd1, 0x48, 0xcf, 0x85, 0x96, 0x89, 0xaa, 0x22, 0x14, 0x73, 0x1d, 0x53, 0xd9, 0x48, 0xe2, 0x77,
0x44, 0x94, 0x20, 0xea, 0x3d, 0xd8, 0xce, 0x36, 0xb5, 0x90, 0x2e, 0x7a, 0x66, 0x93, 0x7b, 0x50, 0x68, 0x6b, 0x04, 0xd4, 0x05, 0x98, 0x67, 0x13, 0x30, 0x3d, 0x5f, 0x10, 0xba, 0x28, 0x43, 0x94,
0x18, 0x9d, 0xbb, 0x16, 0x28, 0x50, 0xb9, 0xc1, 0x3d, 0xb5, 0xa9, 0x34, 0x61, 0x8f, 0x73, 0x27, 0xd4, 0x40, 0x64, 0x05, 0xa2, 0xcf, 0x83, 0xf5, 0xe5, 0xaa, 0x11, 0xd2, 0x45, 0x4f, 0x5d, 0x72,
0x2c, 0x61, 0xa9, 0xee, 0x71, 0x6e, 0xe7, 0xf4, 0x10, 0x52, 0xcb, 0xfd, 0x42, 0x5e, 0xc1, 0x74, 0x07, 0x1a, 0x63, 0x72, 0x37, 0x02, 0x0d, 0xaa, 0x12, 0xa3, 0xa7, 0x27, 0x9c, 0x21, 0xfa, 0x7e,
0xe7, 0xa8, 0xd7, 0xaf, 0xc9, 0xad, 0xac, 0x8b, 0x23, 0x75, 0x71, 0xf7, 0x9e, 0x88, 0x39, 0x43, 0x61, 0xf5, 0xa5, 0xec, 0x36, 0xdc, 0x28, 0xcc, 0xaa, 0x1e, 0x42, 0x7a, 0x29, 0x9c, 0xaa, 0xed,
0xcd, 0x38, 0x0e, 0xa3, 0x1c, 0x28, 0x0f, 0xf9, 0x13, 0x71, 0x3f, 0xa2, 0xe3, 0xca, 0x81, 0x4b, 0x99, 0xcd, 0x2a, 0x7d, 0xfa, 0x2d, 0xdd, 0xb1, 0x4d, 0x71, 0x94, 0x2e, 0xb9, 0xbd, 0x47, 0x62,
0x4b, 0xd3, 0x27, 0x73, 0x4c, 0xeb, 0xce, 0xdd, 0x3b, 0x45, 0xdf, 0x2b, 0x88, 0xe6, 0x51, 0xbc, 0x8e, 0xd1, 0x6e, 0x12, 0x87, 0x51, 0x01, 0x54, 0x44, 0xe2, 0x91, 0xb8, 0x9f, 0xd0, 0x7e, 0x6d,
0xfb, 0x2b, 0x64, 0x6a, 0xa4, 0x37, 0x3a, 0x4a, 0x0e, 0xe4, 0xf3, 0xcb, 0x70, 0xed, 0xeb, 0x75, 0x31, 0x66, 0xa5, 0x99, 0x55, 0x3b, 0xa6, 0x4d, 0x6b, 0xf2, 0xad, 0xa6, 0xfd, 0x39, 0xc4, 0xd3,
0x97, 0x3b, 0x14, 0xb6, 0x08, 0x5c, 0xba, 0x2a, 0x12, 0x3e, 0x96, 0x59, 0x06, 0xee, 0xa0, 0xfd, 0x38, 0xd9, 0x19, 0x35, 0x32, 0xb5, 0xb2, 0xdd, 0x1e, 0xa7, 0x8b, 0xf5, 0xd9, 0x59, 0xb4, 0x0c,
0x3f, 0x20, 0xe0, 0x32, 0xb3, 0x1d, 0x03, 0x92, 0xa8, 0xe5, 0xdc, 0x59, 0x06, 0xfe, 0x0a, 0xed, 0xcd, 0x98, 0x2c, 0x2c, 0x18, 0x57, 0x72, 0x9f, 0x2e, 0xca, 0x8d, 0x92, 0xc8, 0x1c, 0x0b, 0x77,
0x8d, 0xb9, 0xbd, 0xa5, 0xce, 0x63, 0x03, 0xde, 0x45, 0xcd, 0x31, 0x9f, 0x0a, 0xff, 0x42, 0x92, 0xd0, 0xd6, 0x9f, 0xc0, 0x85, 0xca, 0x6c, 0x43, 0x63, 0xa5, 0x6a, 0xd5, 0xaf, 0x8e, 0x85, 0xbf,
0xf3, 0x29, 0x80, 0x0e, 0xda, 0x9f, 0x82, 0xa8, 0x1b, 0x6f, 0x9d, 0xc9, 0x94, 0x2d, 0x21, 0x31, 0x46, 0x4f, 0xc6, 0xc2, 0x5d, 0x53, 0xef, 0xa1, 0xc1, 0xd0, 0x45, 0xbb, 0x63, 0x31, 0x91, 0xe1,
0x51, 0x7f, 0x91, 0x9c, 0x9a, 0x21, 0x11, 0xc4, 0x1b, 0x12, 0xd7, 0x0b, 0x03, 0xd8, 0x15, 0x61, 0xa9, 0x22, 0xe7, 0x63, 0x00, 0x1d, 0xb4, 0x35, 0x01, 0xd9, 0x34, 0x16, 0x4c, 0x26, 0x13, 0x36,
0x4c, 0x45, 0xbf, 0xa7, 0xfe, 0xa2, 0x76, 0xb2, 0x13, 0xd4, 0xc4, 0xd8, 0x70, 0x17, 0x82, 0x64, 0x87, 0xd4, 0x44, 0xff, 0x22, 0xd5, 0x35, 0x43, 0x22, 0x49, 0x30, 0x24, 0x7e, 0x10, 0x71, 0xd8,
0xdb, 0x6e, 0xd8, 0xd9, 0xb7, 0x96, 0x81, 0xfb, 0xe8, 0x58, 0xd1, 0x3d, 0xb6, 0x7e, 0xa4, 0x1d, 0x14, 0x61, 0x4c, 0x65, 0xbf, 0xa7, 0x7f, 0xd1, 0x61, 0x3a, 0x4b, 0x74, 0xc7, 0xb8, 0x70, 0x1b,
0x1a, 0xf4, 0x21, 0xdb, 0x07, 0x0f, 0x1c, 0xef, 0x93, 0xfc, 0x46, 0xc8, 0x8e, 0xd7, 0x3b, 0xf5, 0x81, 0x62, 0xdb, 0x66, 0xd8, 0xf1, 0x77, 0x8e, 0x85, 0xfb, 0x68, 0x5f, 0xd3, 0x3d, 0xb1, 0x7e,
0x7d, 0x96, 0x80, 0x6d, 0xb8, 0xc3, 0x05, 0xef, 0x29, 0x5f, 0x74, 0x15, 0x96, 0x81, 0xbf, 0x41, 0xe0, 0x3a, 0x0c, 0xe8, 0x7d, 0x3e, 0x0f, 0xee, 0x59, 0xfa, 0x07, 0xc5, 0x89, 0x90, 0x2f, 0xbd,
0xe8, 0xc2, 0x63, 0x1c, 0x3e, 0x85, 0x10, 0xc2, 0x63, 0xff, 0xf4, 0x50, 0x15, 0x74, 0xee, 0x79, 0xb7, 0xfa, 0x5d, 0x97, 0x82, 0x5d, 0xb8, 0xc5, 0x25, 0xef, 0x19, 0x5f, 0x4c, 0x15, 0x8e, 0x85,
0x92, 0xb9, 0x7a, 0xe4, 0x72, 0x57, 0xa6, 0xa8, 0x49, 0x6f, 0x7e, 0x51, 0xac, 0xf8, 0x7d, 0x20, 0xbf, 0x45, 0xe8, 0x34, 0x60, 0x02, 0x3e, 0x46, 0x10, 0xc1, 0x43, 0x7f, 0x7a, 0xa8, 0x0b, 0x3a,
0x3f, 0xbc, 0xd4, 0x77, 0x1d, 0x3e, 0xc9, 0x11, 0x4e, 0x0b, 0x53, 0x68, 0xcc, 0x39, 0x2d, 0xb6, 0x09, 0x02, 0xc5, 0x5c, 0xd3, 0x72, 0x85, 0xed, 0x54, 0xd6, 0x64, 0xc3, 0xb2, 0x2c, 0xd6, 0xfc,
0x0c, 0x3c, 0x46, 0x66, 0x3c, 0x00, 0x53, 0x96, 0xf8, 0xab, 0xfb, 0xc4, 0xca, 0x94, 0x0f, 0xb8, 0xde, 0x56, 0x0f, 0x36, 0xfd, 0x1e, 0xc4, 0x07, 0x05, 0xc2, 0x19, 0x61, 0x79, 0xce, 0x66, 0x62,
0x3a, 0x43, 0x0d, 0x35, 0x9d, 0xd7, 0x84, 0x2e, 0xa7, 0xe1, 0x1a, 0x67, 0x3c, 0xbf, 0x93, 0x22, 0xc7, 0xc2, 0x63, 0x64, 0x27, 0x0d, 0x30, 0x61, 0xa9, 0xbf, 0xa6, 0xa7, 0x59, 0xae, 0xbc, 0xc7,
0xd5, 0x9d, 0xba, 0x45, 0xf8, 0xb5, 0xda, 0x6a, 0x43, 0x16, 0x14, 0x6e, 0xd5, 0x6f, 0xb0, 0x2d, 0xd5, 0x31, 0x6a, 0xe9, 0xee, 0xbc, 0x22, 0x74, 0x3e, 0x89, 0x96, 0x38, 0xe7, 0xf9, 0xad, 0x12,
0xf7, 0x72, 0xf0, 0xe6, 0xaf, 0xd7, 0x2b, 0x57, 0xdc, 0x84, 0x8b, 0x8e, 0xc3, 0xd6, 0xdd, 0x7e, 0xe9, 0xdb, 0x69, 0x1a, 0x84, 0xdf, 0xe8, 0xa9, 0x36, 0x64, 0xbc, 0xb4, 0xe3, 0x7e, 0x87, 0x75,
0xdf, 0xa1, 0xdd, 0xe4, 0xc3, 0xbb, 0xab, 0x0c, 0x17, 0x7b, 0xea, 0x8b, 0xbc, 0xff, 0x6f, 0x00, 0xf5, 0x2e, 0x07, 0xaf, 0xff, 0x7e, 0xb5, 0xf0, 0xe5, 0x75, 0x34, 0xeb, 0x78, 0x6c, 0xd9, 0xed,
0x00, 0x00, 0xff, 0xff, 0x54, 0xb6, 0x1e, 0x9c, 0x10, 0x0c, 0x00, 0x00, 0xf7, 0x3d, 0xda, 0x4d, 0x1f, 0xec, 0x5d, 0x6d, 0x38, 0x7b, 0xa2, 0x5f, 0xf2, 0xfd, 0xff, 0x02,
0x00, 0x00, 0xff, 0xff, 0xa5, 0x8d, 0x8a, 0xc5, 0x48, 0x0c, 0x00, 0x00,
} }
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
...@@ -154,6 +154,8 @@ type Chain33Client interface { ...@@ -154,6 +154,8 @@ type Chain33Client interface {
GetPeerInfo(ctx context.Context, in *ReqNil, opts ...grpc.CallOption) (*PeerList, error) GetPeerInfo(ctx context.Context, in *ReqNil, opts ...grpc.CallOption) (*PeerList, error)
//获取最新的Mempool //获取最新的Mempool
GetLastMemPool(ctx context.Context, in *ReqNil, opts ...grpc.CallOption) (*ReplyTxList, error) GetLastMemPool(ctx context.Context, in *ReqNil, opts ...grpc.CallOption) (*ReplyTxList, error)
//获取最新的ProperFee
GetProperFee(ctx context.Context, in *ReqNil, opts ...grpc.CallOption) (*ReplyProperFee, error)
// 获取钱包状态 // 获取钱包状态
GetWalletStatus(ctx context.Context, in *ReqNil, opts ...grpc.CallOption) (*WalletStatus, error) GetWalletStatus(ctx context.Context, in *ReqNil, opts ...grpc.CallOption) (*WalletStatus, error)
//区块浏览器接口 //区块浏览器接口
...@@ -424,6 +426,15 @@ func (c *chain33Client) GetLastMemPool(ctx context.Context, in *ReqNil, opts ... ...@@ -424,6 +426,15 @@ func (c *chain33Client) GetLastMemPool(ctx context.Context, in *ReqNil, opts ...
return out, nil return out, nil
} }
func (c *chain33Client) GetProperFee(ctx context.Context, in *ReqNil, opts ...grpc.CallOption) (*ReplyProperFee, error) {
out := new(ReplyProperFee)
err := c.cc.Invoke(ctx, "/types.chain33/GetProperFee", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *chain33Client) GetWalletStatus(ctx context.Context, in *ReqNil, opts ...grpc.CallOption) (*WalletStatus, error) { func (c *chain33Client) GetWalletStatus(ctx context.Context, in *ReqNil, opts ...grpc.CallOption) (*WalletStatus, error) {
out := new(WalletStatus) out := new(WalletStatus)
err := c.cc.Invoke(ctx, "/types.chain33/GetWalletStatus", in, out, opts...) err := c.cc.Invoke(ctx, "/types.chain33/GetWalletStatus", in, out, opts...)
...@@ -734,6 +745,8 @@ type Chain33Server interface { ...@@ -734,6 +745,8 @@ type Chain33Server interface {
GetPeerInfo(context.Context, *ReqNil) (*PeerList, error) GetPeerInfo(context.Context, *ReqNil) (*PeerList, error)
//获取最新的Mempool //获取最新的Mempool
GetLastMemPool(context.Context, *ReqNil) (*ReplyTxList, error) GetLastMemPool(context.Context, *ReqNil) (*ReplyTxList, error)
//获取最新的ProperFee
GetProperFee(context.Context, *ReqNil) (*ReplyProperFee, error)
// 获取钱包状态 // 获取钱包状态
GetWalletStatus(context.Context, *ReqNil) (*WalletStatus, error) GetWalletStatus(context.Context, *ReqNil) (*WalletStatus, error)
//区块浏览器接口 //区块浏览器接口
...@@ -1207,6 +1220,24 @@ func _Chain33_GetLastMemPool_Handler(srv interface{}, ctx context.Context, dec f ...@@ -1207,6 +1220,24 @@ func _Chain33_GetLastMemPool_Handler(srv interface{}, ctx context.Context, dec f
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _Chain33_GetProperFee_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ReqNil)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(Chain33Server).GetProperFee(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/types.chain33/GetProperFee",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(Chain33Server).GetProperFee(ctx, req.(*ReqNil))
}
return interceptor(ctx, in, info, handler)
}
func _Chain33_GetWalletStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { func _Chain33_GetWalletStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ReqNil) in := new(ReqNil)
if err := dec(in); err != nil { if err := dec(in); err != nil {
...@@ -1826,6 +1857,10 @@ var _Chain33_serviceDesc = grpc.ServiceDesc{ ...@@ -1826,6 +1857,10 @@ var _Chain33_serviceDesc = grpc.ServiceDesc{
Handler: _Chain33_GetLastMemPool_Handler, Handler: _Chain33_GetLastMemPool_Handler,
}, },
{ {
MethodName: "GetProperFee",
Handler: _Chain33_GetProperFee_Handler,
},
{
MethodName: "GetWalletStatus", MethodName: "GetWalletStatus",
Handler: _Chain33_GetWalletStatus_Handler, Handler: _Chain33_GetWalletStatus_Handler,
}, },
......
...@@ -5,9 +5,8 @@ package types ...@@ -5,9 +5,8 @@ package types
import ( import (
fmt "fmt" fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto" proto "github.com/golang/protobuf/proto"
math "math"
) )
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
...@@ -1377,6 +1376,45 @@ func (m *ReplyTxList) GetTxs() []*Transaction { ...@@ -1377,6 +1376,45 @@ func (m *ReplyTxList) GetTxs() []*Transaction {
return nil return nil
} }
type ReplyProperFee struct {
ProperFee int64 `protobuf:"varint,1,opt,name=properFee,proto3" json:"properFee,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ReplyProperFee) Reset() { *m = ReplyProperFee{} }
func (m *ReplyProperFee) String() string { return proto.CompactTextString(m) }
func (*ReplyProperFee) ProtoMessage() {}
func (*ReplyProperFee) Descriptor() ([]byte, []int) {
return fileDescriptor_2cc4e03d2c28c490, []int{23}
}
func (m *ReplyProperFee) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReplyProperFee.Unmarshal(m, b)
}
func (m *ReplyProperFee) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ReplyProperFee.Marshal(b, m, deterministic)
}
func (m *ReplyProperFee) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReplyProperFee.Merge(m, src)
}
func (m *ReplyProperFee) XXX_Size() int {
return xxx_messageInfo_ReplyProperFee.Size(m)
}
func (m *ReplyProperFee) XXX_DiscardUnknown() {
xxx_messageInfo_ReplyProperFee.DiscardUnknown(m)
}
var xxx_messageInfo_ReplyProperFee proto.InternalMessageInfo
func (m *ReplyProperFee) GetProperFee() int64 {
if m != nil {
return m.ProperFee
}
return 0
}
type TxHashList struct { type TxHashList struct {
Hashes [][]byte `protobuf:"bytes,1,rep,name=hashes,proto3" json:"hashes,omitempty"` Hashes [][]byte `protobuf:"bytes,1,rep,name=hashes,proto3" json:"hashes,omitempty"`
Count int64 `protobuf:"varint,2,opt,name=count,proto3" json:"count,omitempty"` Count int64 `protobuf:"varint,2,opt,name=count,proto3" json:"count,omitempty"`
...@@ -1390,7 +1428,7 @@ func (m *TxHashList) Reset() { *m = TxHashList{} } ...@@ -1390,7 +1428,7 @@ func (m *TxHashList) Reset() { *m = TxHashList{} }
func (m *TxHashList) String() string { return proto.CompactTextString(m) } func (m *TxHashList) String() string { return proto.CompactTextString(m) }
func (*TxHashList) ProtoMessage() {} func (*TxHashList) ProtoMessage() {}
func (*TxHashList) Descriptor() ([]byte, []int) { func (*TxHashList) Descriptor() ([]byte, []int) {
return fileDescriptor_2cc4e03d2c28c490, []int{23} return fileDescriptor_2cc4e03d2c28c490, []int{24}
} }
func (m *TxHashList) XXX_Unmarshal(b []byte) error { func (m *TxHashList) XXX_Unmarshal(b []byte) error {
...@@ -1443,7 +1481,7 @@ func (m *ReplyTxInfos) Reset() { *m = ReplyTxInfos{} } ...@@ -1443,7 +1481,7 @@ func (m *ReplyTxInfos) Reset() { *m = ReplyTxInfos{} }
func (m *ReplyTxInfos) String() string { return proto.CompactTextString(m) } func (m *ReplyTxInfos) String() string { return proto.CompactTextString(m) }
func (*ReplyTxInfos) ProtoMessage() {} func (*ReplyTxInfos) ProtoMessage() {}
func (*ReplyTxInfos) Descriptor() ([]byte, []int) { func (*ReplyTxInfos) Descriptor() ([]byte, []int) {
return fileDescriptor_2cc4e03d2c28c490, []int{24} return fileDescriptor_2cc4e03d2c28c490, []int{25}
} }
func (m *ReplyTxInfos) XXX_Unmarshal(b []byte) error { func (m *ReplyTxInfos) XXX_Unmarshal(b []byte) error {
...@@ -1483,7 +1521,7 @@ func (m *ReceiptLog) Reset() { *m = ReceiptLog{} } ...@@ -1483,7 +1521,7 @@ func (m *ReceiptLog) Reset() { *m = ReceiptLog{} }
func (m *ReceiptLog) String() string { return proto.CompactTextString(m) } func (m *ReceiptLog) String() string { return proto.CompactTextString(m) }
func (*ReceiptLog) ProtoMessage() {} func (*ReceiptLog) ProtoMessage() {}
func (*ReceiptLog) Descriptor() ([]byte, []int) { func (*ReceiptLog) Descriptor() ([]byte, []int) {
return fileDescriptor_2cc4e03d2c28c490, []int{25} return fileDescriptor_2cc4e03d2c28c490, []int{26}
} }
func (m *ReceiptLog) XXX_Unmarshal(b []byte) error { func (m *ReceiptLog) XXX_Unmarshal(b []byte) error {
...@@ -1534,7 +1572,7 @@ func (m *Receipt) Reset() { *m = Receipt{} } ...@@ -1534,7 +1572,7 @@ func (m *Receipt) Reset() { *m = Receipt{} }
func (m *Receipt) String() string { return proto.CompactTextString(m) } func (m *Receipt) String() string { return proto.CompactTextString(m) }
func (*Receipt) ProtoMessage() {} func (*Receipt) ProtoMessage() {}
func (*Receipt) Descriptor() ([]byte, []int) { func (*Receipt) Descriptor() ([]byte, []int) {
return fileDescriptor_2cc4e03d2c28c490, []int{26} return fileDescriptor_2cc4e03d2c28c490, []int{27}
} }
func (m *Receipt) XXX_Unmarshal(b []byte) error { func (m *Receipt) XXX_Unmarshal(b []byte) error {
...@@ -1588,7 +1626,7 @@ func (m *ReceiptData) Reset() { *m = ReceiptData{} } ...@@ -1588,7 +1626,7 @@ func (m *ReceiptData) Reset() { *m = ReceiptData{} }
func (m *ReceiptData) String() string { return proto.CompactTextString(m) } func (m *ReceiptData) String() string { return proto.CompactTextString(m) }
func (*ReceiptData) ProtoMessage() {} func (*ReceiptData) ProtoMessage() {}
func (*ReceiptData) Descriptor() ([]byte, []int) { func (*ReceiptData) Descriptor() ([]byte, []int) {
return fileDescriptor_2cc4e03d2c28c490, []int{27} return fileDescriptor_2cc4e03d2c28c490, []int{28}
} }
func (m *ReceiptData) XXX_Unmarshal(b []byte) error { func (m *ReceiptData) XXX_Unmarshal(b []byte) error {
...@@ -1639,7 +1677,7 @@ func (m *TxResult) Reset() { *m = TxResult{} } ...@@ -1639,7 +1677,7 @@ func (m *TxResult) Reset() { *m = TxResult{} }
func (m *TxResult) String() string { return proto.CompactTextString(m) } func (m *TxResult) String() string { return proto.CompactTextString(m) }
func (*TxResult) ProtoMessage() {} func (*TxResult) ProtoMessage() {}
func (*TxResult) Descriptor() ([]byte, []int) { func (*TxResult) Descriptor() ([]byte, []int) {
return fileDescriptor_2cc4e03d2c28c490, []int{28} return fileDescriptor_2cc4e03d2c28c490, []int{29}
} }
func (m *TxResult) XXX_Unmarshal(b []byte) error { func (m *TxResult) XXX_Unmarshal(b []byte) error {
...@@ -1722,7 +1760,7 @@ func (m *TransactionDetail) Reset() { *m = TransactionDetail{} } ...@@ -1722,7 +1760,7 @@ func (m *TransactionDetail) Reset() { *m = TransactionDetail{} }
func (m *TransactionDetail) String() string { return proto.CompactTextString(m) } func (m *TransactionDetail) String() string { return proto.CompactTextString(m) }
func (*TransactionDetail) ProtoMessage() {} func (*TransactionDetail) ProtoMessage() {}
func (*TransactionDetail) Descriptor() ([]byte, []int) { func (*TransactionDetail) Descriptor() ([]byte, []int) {
return fileDescriptor_2cc4e03d2c28c490, []int{29} return fileDescriptor_2cc4e03d2c28c490, []int{30}
} }
func (m *TransactionDetail) XXX_Unmarshal(b []byte) error { func (m *TransactionDetail) XXX_Unmarshal(b []byte) error {
...@@ -1824,7 +1862,7 @@ func (m *TransactionDetails) Reset() { *m = TransactionDetails{} } ...@@ -1824,7 +1862,7 @@ func (m *TransactionDetails) Reset() { *m = TransactionDetails{} }
func (m *TransactionDetails) String() string { return proto.CompactTextString(m) } func (m *TransactionDetails) String() string { return proto.CompactTextString(m) }
func (*TransactionDetails) ProtoMessage() {} func (*TransactionDetails) ProtoMessage() {}
func (*TransactionDetails) Descriptor() ([]byte, []int) { func (*TransactionDetails) Descriptor() ([]byte, []int) {
return fileDescriptor_2cc4e03d2c28c490, []int{30} return fileDescriptor_2cc4e03d2c28c490, []int{31}
} }
func (m *TransactionDetails) XXX_Unmarshal(b []byte) error { func (m *TransactionDetails) XXX_Unmarshal(b []byte) error {
...@@ -1863,7 +1901,7 @@ func (m *ReqAddrs) Reset() { *m = ReqAddrs{} } ...@@ -1863,7 +1901,7 @@ func (m *ReqAddrs) Reset() { *m = ReqAddrs{} }
func (m *ReqAddrs) String() string { return proto.CompactTextString(m) } func (m *ReqAddrs) String() string { return proto.CompactTextString(m) }
func (*ReqAddrs) ProtoMessage() {} func (*ReqAddrs) ProtoMessage() {}
func (*ReqAddrs) Descriptor() ([]byte, []int) { func (*ReqAddrs) Descriptor() ([]byte, []int) {
return fileDescriptor_2cc4e03d2c28c490, []int{31} return fileDescriptor_2cc4e03d2c28c490, []int{32}
} }
func (m *ReqAddrs) XXX_Unmarshal(b []byte) error { func (m *ReqAddrs) XXX_Unmarshal(b []byte) error {
...@@ -1902,7 +1940,7 @@ func (m *ReqDecodeRawTransaction) Reset() { *m = ReqDecodeRawTransaction ...@@ -1902,7 +1940,7 @@ func (m *ReqDecodeRawTransaction) Reset() { *m = ReqDecodeRawTransaction
func (m *ReqDecodeRawTransaction) String() string { return proto.CompactTextString(m) } func (m *ReqDecodeRawTransaction) String() string { return proto.CompactTextString(m) }
func (*ReqDecodeRawTransaction) ProtoMessage() {} func (*ReqDecodeRawTransaction) ProtoMessage() {}
func (*ReqDecodeRawTransaction) Descriptor() ([]byte, []int) { func (*ReqDecodeRawTransaction) Descriptor() ([]byte, []int) {
return fileDescriptor_2cc4e03d2c28c490, []int{32} return fileDescriptor_2cc4e03d2c28c490, []int{33}
} }
func (m *ReqDecodeRawTransaction) XXX_Unmarshal(b []byte) error { func (m *ReqDecodeRawTransaction) XXX_Unmarshal(b []byte) error {
...@@ -1942,7 +1980,7 @@ func (m *UserWrite) Reset() { *m = UserWrite{} } ...@@ -1942,7 +1980,7 @@ func (m *UserWrite) Reset() { *m = UserWrite{} }
func (m *UserWrite) String() string { return proto.CompactTextString(m) } func (m *UserWrite) String() string { return proto.CompactTextString(m) }
func (*UserWrite) ProtoMessage() {} func (*UserWrite) ProtoMessage() {}
func (*UserWrite) Descriptor() ([]byte, []int) { func (*UserWrite) Descriptor() ([]byte, []int) {
return fileDescriptor_2cc4e03d2c28c490, []int{33} return fileDescriptor_2cc4e03d2c28c490, []int{34}
} }
func (m *UserWrite) XXX_Unmarshal(b []byte) error { func (m *UserWrite) XXX_Unmarshal(b []byte) error {
...@@ -1990,7 +2028,7 @@ func (m *UpgradeMeta) Reset() { *m = UpgradeMeta{} } ...@@ -1990,7 +2028,7 @@ func (m *UpgradeMeta) Reset() { *m = UpgradeMeta{} }
func (m *UpgradeMeta) String() string { return proto.CompactTextString(m) } func (m *UpgradeMeta) String() string { return proto.CompactTextString(m) }
func (*UpgradeMeta) ProtoMessage() {} func (*UpgradeMeta) ProtoMessage() {}
func (*UpgradeMeta) Descriptor() ([]byte, []int) { func (*UpgradeMeta) Descriptor() ([]byte, []int) {
return fileDescriptor_2cc4e03d2c28c490, []int{34} return fileDescriptor_2cc4e03d2c28c490, []int{35}
} }
func (m *UpgradeMeta) XXX_Unmarshal(b []byte) error { func (m *UpgradeMeta) XXX_Unmarshal(b []byte) error {
...@@ -2056,6 +2094,7 @@ func init() { ...@@ -2056,6 +2094,7 @@ func init() {
proto.RegisterType((*ReplyTxInfo)(nil), "types.ReplyTxInfo") proto.RegisterType((*ReplyTxInfo)(nil), "types.ReplyTxInfo")
proto.RegisterType((*ReqTxList)(nil), "types.ReqTxList") proto.RegisterType((*ReqTxList)(nil), "types.ReqTxList")
proto.RegisterType((*ReplyTxList)(nil), "types.ReplyTxList") proto.RegisterType((*ReplyTxList)(nil), "types.ReplyTxList")
proto.RegisterType((*ReplyProperFee)(nil), "types.ReplyProperFee")
proto.RegisterType((*TxHashList)(nil), "types.TxHashList") proto.RegisterType((*TxHashList)(nil), "types.TxHashList")
proto.RegisterType((*ReplyTxInfos)(nil), "types.ReplyTxInfos") proto.RegisterType((*ReplyTxInfos)(nil), "types.ReplyTxInfos")
proto.RegisterType((*ReceiptLog)(nil), "types.ReceiptLog") proto.RegisterType((*ReceiptLog)(nil), "types.ReceiptLog")
...@@ -2073,89 +2112,90 @@ func init() { ...@@ -2073,89 +2112,90 @@ func init() {
func init() { proto.RegisterFile("transaction.proto", fileDescriptor_2cc4e03d2c28c490) } func init() { proto.RegisterFile("transaction.proto", fileDescriptor_2cc4e03d2c28c490) }
var fileDescriptor_2cc4e03d2c28c490 = []byte{ var fileDescriptor_2cc4e03d2c28c490 = []byte{
// 1329 bytes of a gzipped FileDescriptorProto // 1348 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x57, 0xdd, 0x8e, 0x13, 0xc7, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x57, 0xdb, 0x8e, 0x13, 0x47,
0x12, 0xd6, 0xcc, 0xd8, 0x5e, 0xbb, 0x6c, 0x38, 0xec, 0x08, 0x2d, 0x16, 0xe2, 0xc0, 0x9e, 0x16, 0x13, 0x96, 0x67, 0x6c, 0xaf, 0x5d, 0x36, 0xfc, 0xec, 0x08, 0x2d, 0x16, 0xe2, 0x87, 0x4d, 0x8b,
0x47, 0x42, 0x08, 0xed, 0x4a, 0xbb, 0xdc, 0x9d, 0x23, 0x25, 0xc0, 0x46, 0x80, 0x16, 0x48, 0xd2, 0x48, 0x08, 0x21, 0xaf, 0xb4, 0xcb, 0x5d, 0x22, 0x25, 0xc0, 0x26, 0x80, 0x16, 0x08, 0x69, 0xcc,
0x98, 0x1f, 0x25, 0x51, 0xa4, 0xde, 0x71, 0xad, 0xdd, 0xc1, 0x9e, 0xf6, 0xce, 0xb4, 0x97, 0xf1, 0x41, 0x49, 0x14, 0xa9, 0x77, 0x5c, 0x6b, 0x77, 0xb0, 0xa7, 0xbd, 0x33, 0xed, 0x65, 0xfc, 0x02,
0x0b, 0xe4, 0x26, 0xb9, 0xcb, 0x23, 0xe5, 0x05, 0xf2, 0x18, 0x79, 0x8c, 0xa8, 0xab, 0xbb, 0x67, 0xb9, 0x49, 0xee, 0xf2, 0x48, 0x79, 0x81, 0x3c, 0x46, 0x1e, 0x23, 0xea, 0xea, 0xee, 0x99, 0xf6,
0xda, 0xfb, 0x83, 0xb8, 0x88, 0x94, 0xbb, 0xfe, 0xaa, 0xcb, 0x55, 0x5f, 0xfd, 0x4e, 0x1b, 0x36, 0x1e, 0x10, 0x17, 0x91, 0x72, 0xd7, 0x5f, 0x75, 0xb9, 0xea, 0xab, 0xe3, 0xb4, 0x61, 0x53, 0xe7,
0x75, 0x21, 0xf2, 0x52, 0x64, 0x5a, 0xaa, 0x7c, 0x67, 0x51, 0x28, 0xad, 0xd2, 0xb6, 0x5e, 0x2d, 0x22, 0x2b, 0x44, 0xaa, 0xa5, 0xca, 0x86, 0x8b, 0x5c, 0x69, 0x95, 0xb4, 0xf4, 0x6a, 0x81, 0xc5,
0xb0, 0xbc, 0x39, 0xc8, 0xd4, 0x7c, 0xee, 0x85, 0xec, 0x25, 0x5c, 0x79, 0x54, 0x96, 0xa8, 0xcb, 0xf5, 0x7e, 0xaa, 0xe6, 0x73, 0x2f, 0x64, 0xcf, 0xe1, 0xd2, 0x83, 0xa2, 0x40, 0x5d, 0x3c, 0xc6,
0xa7, 0x98, 0x63, 0x29, 0xcb, 0x74, 0x0b, 0x3a, 0x62, 0xae, 0x96, 0xb9, 0x1e, 0xc6, 0xdb, 0xd1, 0x0c, 0x0b, 0x59, 0x24, 0x5b, 0xd0, 0x16, 0x73, 0xb5, 0xcc, 0xf4, 0x20, 0xda, 0x6e, 0xdc, 0x89,
0xbd, 0x84, 0x3b, 0x94, 0xde, 0x85, 0x2b, 0x05, 0xea, 0x65, 0x91, 0x3f, 0x1a, 0x8f, 0x0b, 0x2c, 0xb9, 0x43, 0xc9, 0x6d, 0xb8, 0x94, 0xa3, 0x5e, 0xe6, 0xd9, 0x83, 0xf1, 0x38, 0xc7, 0xa2, 0x18,
0xcb, 0x61, 0xb2, 0x1d, 0xdd, 0xeb, 0xf1, 0x75, 0x21, 0xfb, 0x35, 0x82, 0xeb, 0xd6, 0xde, 0xc8, 0xc4, 0xdb, 0x8d, 0x3b, 0x5d, 0xbe, 0x2e, 0x64, 0xbf, 0x37, 0xe0, 0xaa, 0xb5, 0x37, 0x32, 0xfe,
0xf8, 0x3f, 0xc6, 0x62, 0xa4, 0xbe, 0xaa, 0x30, 0x4b, 0x6f, 0x41, 0x2f, 0x53, 0x32, 0xd7, 0xea, 0x8f, 0x30, 0x1f, 0xa9, 0x6f, 0x4a, 0x4c, 0x93, 0x1b, 0xd0, 0x4d, 0x95, 0xcc, 0xb4, 0x7a, 0x8f,
0x03, 0xe6, 0xc3, 0x88, 0x7e, 0xda, 0x08, 0x2e, 0x75, 0x9a, 0x42, 0x2b, 0x57, 0x1a, 0xc9, 0xd7, 0xd9, 0xa0, 0x41, 0x3f, 0xad, 0x05, 0x17, 0x3a, 0x4d, 0xa0, 0x99, 0x29, 0x8d, 0xe4, 0xab, 0xcf,
0x80, 0xd3, 0x39, 0xbd, 0x09, 0x5d, 0xac, 0x30, 0x7b, 0x25, 0xe6, 0x38, 0x6c, 0x91, 0xa1, 0x1a, 0xe9, 0x9c, 0x5c, 0x87, 0x0e, 0x96, 0x98, 0xbe, 0x10, 0x73, 0x1c, 0x34, 0xc9, 0x50, 0x85, 0x93,
0xa7, 0x57, 0x21, 0xd6, 0x6a, 0xd8, 0x26, 0x69, 0xac, 0x15, 0xfb, 0x39, 0x82, 0xab, 0x96, 0xce, 0xcb, 0x10, 0x69, 0x35, 0x68, 0x91, 0x34, 0xd2, 0x8a, 0xfd, 0xda, 0x80, 0xcb, 0x96, 0xce, 0x5b,
0x3b, 0xa9, 0xa7, 0xe3, 0x42, 0x7c, 0xfc, 0x87, 0x88, 0xfc, 0xe4, 0x79, 0xf8, 0xb4, 0xfc, 0x8d, 0xa9, 0xa7, 0xe3, 0x5c, 0x7c, 0xf8, 0x8f, 0x88, 0xfc, 0xe2, 0x79, 0xf8, 0xb4, 0xfc, 0x8b, 0x3c,
0x3c, 0xac, 0xaf, 0x56, 0xed, 0xeb, 0x10, 0xda, 0xe4, 0xcb, 0x28, 0x1b, 0x42, 0xce, 0x3a, 0x9d, 0xac, 0xaf, 0x66, 0xe5, 0xeb, 0x00, 0x5a, 0xe4, 0xcb, 0x28, 0x1b, 0x42, 0xce, 0x3a, 0x9d, 0x8d,
0x8d, 0xe1, 0x72, 0x35, 0x3f, 0x52, 0x33, 0x32, 0xdc, 0xe3, 0x0e, 0x05, 0x0e, 0x93, 0xd0, 0x21, 0xe1, 0x62, 0x35, 0x3f, 0x54, 0x33, 0x32, 0xdc, 0xe5, 0x0e, 0x05, 0x0e, 0xe3, 0xd0, 0x21, 0xfb,
0xfb, 0x33, 0x82, 0xee, 0x93, 0x02, 0x85, 0xc6, 0x51, 0xe5, 0x3c, 0x45, 0xde, 0xd3, 0xa5, 0x2c, 0xbb, 0x01, 0x9d, 0x47, 0x39, 0x0a, 0x8d, 0xa3, 0xd2, 0x79, 0x6a, 0x78, 0x4f, 0x17, 0xb2, 0xbc,
0xaf, 0x41, 0x72, 0x8c, 0xe8, 0x2c, 0x99, 0x63, 0xcd, 0xbb, 0x15, 0xf0, 0xbe, 0x0d, 0x20, 0xeb, 0x02, 0xf1, 0x11, 0xa2, 0xb3, 0x64, 0x8e, 0x15, 0xef, 0x66, 0xc0, 0xfb, 0x26, 0x80, 0xac, 0xea,
0xba, 0x50, 0xae, 0xba, 0x3c, 0x90, 0xa4, 0x43, 0xd8, 0x90, 0xe5, 0x88, 0xf2, 0xd3, 0xa1, 0x4b, 0x42, 0xb9, 0xea, 0xf0, 0x40, 0x92, 0x0c, 0x60, 0x43, 0x16, 0x23, 0xca, 0x4f, 0x9b, 0x2e, 0x3d,
0x0f, 0xd3, 0x6d, 0xe8, 0x53, 0x9a, 0x5e, 0xdb, 0x48, 0x36, 0x88, 0x50, 0x28, 0x5a, 0xab, 0x4d, 0x4c, 0xb6, 0xa1, 0x47, 0x69, 0x7a, 0x65, 0x23, 0xd9, 0x20, 0x42, 0xa1, 0x68, 0xad, 0x36, 0x9d,
0xf7, 0x4c, 0x6d, 0xb6, 0xa0, 0x63, 0xce, 0x58, 0x0c, 0x7b, 0x36, 0x05, 0x16, 0xb1, 0xf7, 0x30, 0x53, 0xb5, 0xd9, 0x82, 0xb6, 0x39, 0x63, 0x3e, 0xe8, 0xda, 0x14, 0x58, 0xc4, 0xde, 0x41, 0x9f,
0xe0, 0xf8, 0xae, 0x90, 0x1a, 0xb9, 0xf8, 0xe8, 0xa2, 0xad, 0xea, 0x68, 0x7d, 0xf4, 0x49, 0x18, 0xe3, 0xdb, 0x5c, 0x6a, 0xe4, 0xe2, 0x83, 0x8b, 0xb6, 0xac, 0xa2, 0xf5, 0xd1, 0xc7, 0x61, 0xf4,
0x3d, 0x56, 0x0b, 0x59, 0xf8, 0xea, 0x3b, 0xe4, 0xa3, 0x6f, 0xd7, 0xd1, 0xb3, 0xfb, 0xb0, 0xe5, 0x58, 0x2e, 0x64, 0xee, 0xab, 0xef, 0x90, 0x8f, 0xbe, 0x55, 0x45, 0xcf, 0xee, 0xc2, 0x96, 0xcb,
0x72, 0xd8, 0x0c, 0xe5, 0xd3, 0x42, 0x2d, 0x17, 0x46, 0x57, 0x57, 0xe5, 0x30, 0xda, 0x4e, 0xee, 0x61, 0x3d, 0x94, 0x8f, 0x73, 0xb5, 0x5c, 0x18, 0x5d, 0x5d, 0x16, 0x83, 0xc6, 0x76, 0x7c, 0xa7,
0xf5, 0xb8, 0x39, 0xb2, 0xdb, 0xd0, 0x7d, 0x93, 0x97, 0x72, 0x92, 0x8f, 0x2a, 0x93, 0xb5, 0xb1, 0xcb, 0xcd, 0x91, 0xdd, 0x84, 0xce, 0xeb, 0xac, 0x90, 0x93, 0x6c, 0x54, 0x9a, 0xac, 0x8d, 0x85,
0xd0, 0x82, 0x38, 0x0c, 0x38, 0x9d, 0x99, 0x82, 0xfe, 0x2b, 0xf5, 0x58, 0xcc, 0x44, 0x9e, 0x99, 0x16, 0xc4, 0xa1, 0xcf, 0xe9, 0xcc, 0x14, 0xf4, 0x5e, 0xa8, 0x87, 0x62, 0x26, 0xb2, 0xd4, 0x94,
0x92, 0x5c, 0x87, 0xb6, 0xae, 0x9e, 0xa1, 0xe7, 0x69, 0x81, 0x49, 0xdd, 0x42, 0xac, 0xcc, 0x50, 0xe4, 0x2a, 0xb4, 0x74, 0xf9, 0x04, 0x3d, 0x4f, 0x0b, 0x4c, 0xea, 0x16, 0x62, 0x65, 0x86, 0xd2,
0xba, 0x32, 0x7b, 0x48, 0x37, 0x85, 0x3c, 0xfd, 0x80, 0x2b, 0x17, 0x89, 0x87, 0x97, 0x85, 0xc3, 0x95, 0xd9, 0x43, 0xba, 0xc9, 0xe5, 0xc9, 0x7b, 0x5c, 0xb9, 0x48, 0x3c, 0xbc, 0x28, 0x1c, 0xf6,
0x7e, 0x84, 0xee, 0x6b, 0x39, 0xc9, 0x71, 0x3c, 0xaa, 0x8c, 0xce, 0x92, 0xc8, 0x39, 0x4a, 0x0e, 0x33, 0x74, 0x5e, 0xc9, 0x49, 0x86, 0xe3, 0x51, 0x69, 0x74, 0x96, 0x44, 0xce, 0x51, 0x72, 0xc8,
0x19, 0xa2, 0x24, 0x8d, 0x2d, 0x51, 0x92, 0x6d, 0x41, 0x67, 0xb1, 0x3c, 0xf2, 0x8e, 0x06, 0xdc, 0x10, 0x25, 0x69, 0x64, 0x89, 0x92, 0x6c, 0x0b, 0xda, 0x8b, 0xe5, 0xa1, 0x77, 0xd4, 0xe7, 0x0e,
0x21, 0x4a, 0xe3, 0x8a, 0x7c, 0xb4, 0x79, 0xac, 0x57, 0xec, 0x97, 0x18, 0xfa, 0x41, 0x5e, 0x82, 0x51, 0x1a, 0x57, 0xe4, 0xa3, 0xc5, 0x23, 0xbd, 0x62, 0xbf, 0x45, 0xd0, 0x0b, 0xf2, 0x12, 0x94,
0xf2, 0x38, 0x1f, 0x16, 0xb9, 0x98, 0x66, 0x4a, 0x8c, 0x9d, 0x1b, 0x0f, 0xd3, 0x1d, 0xe8, 0x19, 0xc7, 0xf9, 0xb0, 0xc8, 0xc5, 0x34, 0x53, 0x62, 0xec, 0xdc, 0x78, 0x98, 0x0c, 0xa1, 0x6b, 0x3c,
0x8f, 0x42, 0x2f, 0x0b, 0xdb, 0x74, 0xfd, 0xbd, 0x6b, 0x3b, 0xb4, 0xec, 0x76, 0x5e, 0x7b, 0x39, 0x0a, 0xbd, 0xcc, 0x6d, 0xd3, 0xf5, 0x76, 0xaf, 0x0c, 0x69, 0xd9, 0x0d, 0x5f, 0x79, 0x39, 0xaf,
0x6f, 0x54, 0x7c, 0x81, 0x5a, 0x4d, 0x7b, 0x36, 0xb1, 0xdb, 0xaa, 0xf9, 0x52, 0x5e, 0x87, 0x76, 0x55, 0x7c, 0x81, 0x9a, 0x75, 0x7b, 0xd6, 0xb1, 0xdb, 0xaa, 0xf9, 0x52, 0x5e, 0x85, 0x56, 0xa6,
0xae, 0xf2, 0x0c, 0xa9, 0x01, 0x13, 0x6e, 0x81, 0x6b, 0x84, 0x8d, 0xba, 0x11, 0x6e, 0x03, 0x4c, 0xb2, 0x14, 0xa9, 0x01, 0x63, 0x6e, 0x81, 0x6b, 0x84, 0x8d, 0xaa, 0x11, 0x6e, 0x02, 0x4c, 0x4c,
0x4c, 0x35, 0x9f, 0xd0, 0x28, 0x74, 0x29, 0xb2, 0x40, 0x62, 0xac, 0x4f, 0x51, 0x8c, 0x5d, 0xc3, 0x35, 0x1f, 0xd1, 0x28, 0x74, 0x28, 0xb2, 0x40, 0x62, 0xac, 0x4f, 0x51, 0x8c, 0x5d, 0xc3, 0xf5,
0x0d, 0xb8, 0x43, 0x34, 0x14, 0x58, 0xe9, 0x21, 0xb8, 0xa1, 0xc0, 0x4a, 0xb3, 0x87, 0x30, 0x08, 0xb9, 0x43, 0x34, 0x14, 0x58, 0xea, 0x01, 0xb8, 0xa1, 0xc0, 0x52, 0xb3, 0xfb, 0xd0, 0x0f, 0x92,
0x92, 0x51, 0xa6, 0x77, 0x9b, 0x06, 0xe9, 0xef, 0xa5, 0x2e, 0xaa, 0x40, 0xc3, 0x36, 0xcd, 0x17, 0x51, 0x24, 0xb7, 0xeb, 0x06, 0xe9, 0xed, 0x26, 0x2e, 0xaa, 0x40, 0xc3, 0x36, 0xcd, 0x57, 0x70,
0x70, 0x85, 0xcb, 0x7c, 0x52, 0x47, 0x9b, 0xee, 0x40, 0x5b, 0x6a, 0x9c, 0xfb, 0x1f, 0x0e, 0xdd, 0x89, 0xcb, 0x6c, 0x52, 0x45, 0x9b, 0x0c, 0xa1, 0x25, 0x35, 0xce, 0xfd, 0x0f, 0x07, 0xee, 0x87,
0x0f, 0xd7, 0x94, 0x9e, 0x6b, 0x9c, 0x73, 0xab, 0xc6, 0x9e, 0xc3, 0xe6, 0xb9, 0xbb, 0xa0, 0x82, 0x6b, 0x4a, 0x4f, 0x35, 0xce, 0xb9, 0x55, 0x63, 0x4f, 0x61, 0xf3, 0xcc, 0x5d, 0x50, 0x41, 0x63,
0xc6, 0x4a, 0x53, 0xc1, 0x5b, 0x61, 0xbe, 0x63, 0xba, 0x6a, 0x04, 0xec, 0x5b, 0xe8, 0x35, 0x3c, 0xa5, 0xae, 0xe0, 0x8d, 0x30, 0xdf, 0x11, 0x5d, 0xd5, 0x02, 0xf6, 0x3d, 0x74, 0x6b, 0x1e, 0xb6,
0x6c, 0xb1, 0x23, 0x5f, 0xec, 0xc0, 0x64, 0xbc, 0xd6, 0x14, 0xb7, 0xce, 0x96, 0x70, 0xcd, 0xe4, 0xd8, 0x0d, 0x5f, 0xec, 0xc0, 0x64, 0xb4, 0xd6, 0x14, 0x37, 0x4e, 0x97, 0x70, 0xcd, 0xe4, 0x4f,
0x0f, 0x30, 0x30, 0xcd, 0xfb, 0xf5, 0x29, 0x16, 0xa7, 0x12, 0x69, 0x33, 0x14, 0x98, 0xc9, 0x53, 0xd0, 0x37, 0xcd, 0xfb, 0xdd, 0x09, 0xe6, 0x27, 0x12, 0x69, 0x33, 0xe4, 0x98, 0xca, 0x13, 0xd7,
0xd7, 0x23, 0x09, 0xf7, 0xd0, 0xdc, 0x1c, 0xd9, 0xd9, 0x70, 0x2b, 0xc9, 0x43, 0x73, 0xa3, 0xab, 0x23, 0x31, 0xf7, 0xd0, 0xdc, 0x1c, 0xda, 0xd9, 0x70, 0x2b, 0xc9, 0x43, 0x73, 0xa3, 0xcb, 0x47,
0x27, 0xc1, 0x86, 0xf3, 0x90, 0xfd, 0x16, 0xc1, 0x06, 0xc7, 0x13, 0x1a, 0x8f, 0x14, 0x5a, 0xc2, 0xc1, 0x86, 0xf3, 0x90, 0xfd, 0xd1, 0x80, 0x0d, 0x8e, 0xc7, 0x34, 0x1e, 0x09, 0x34, 0x85, 0x99,
0x4c, 0x8d, 0x5b, 0x99, 0xc2, 0xc9, 0x8e, 0x67, 0x62, 0x42, 0x06, 0xdb, 0x9c, 0xce, 0xa6, 0x31, 0x1a, 0xb7, 0x32, 0x85, 0x93, 0x1d, 0xcd, 0xc4, 0x84, 0x0c, 0xb6, 0x38, 0x9d, 0x4d, 0x63, 0xa4,
0xb2, 0xda, 0x56, 0x9b, 0x5b, 0x60, 0xa2, 0x18, 0xcb, 0x02, 0xa9, 0x30, 0xae, 0xc3, 0x1b, 0x81, 0x95, 0xad, 0x16, 0xb7, 0xc0, 0x44, 0x31, 0x96, 0x39, 0x52, 0x61, 0x5c, 0x87, 0xd7, 0x02, 0xdb,
0x6d, 0x03, 0x39, 0x99, 0x6a, 0xdf, 0x64, 0x16, 0x19, 0x5b, 0x32, 0x1f, 0x63, 0xe5, 0x9b, 0x8c, 0x06, 0x72, 0x32, 0xd5, 0xbe, 0xc9, 0x2c, 0x32, 0xb6, 0x64, 0x36, 0xc6, 0xd2, 0x37, 0x19, 0x01,
0x00, 0x7b, 0x0f, 0xc0, 0xf1, 0xe4, 0x9b, 0x42, 0x9e, 0x8a, 0x6c, 0xd5, 0xf8, 0x8b, 0x2e, 0xf5, 0xf6, 0x0e, 0x80, 0xe3, 0xf1, 0xcb, 0x5c, 0x9e, 0x88, 0x74, 0x55, 0xfb, 0x6b, 0x5c, 0xe8, 0x2f,
0x17, 0x5f, 0xee, 0x2f, 0x09, 0xfd, 0xb1, 0x1b, 0xd0, 0x7e, 0x86, 0xd5, 0xf9, 0x05, 0xc7, 0x96, 0xba, 0xd8, 0x5f, 0x1c, 0xfa, 0x63, 0xd7, 0xa0, 0xf5, 0x04, 0xcb, 0xb3, 0x0b, 0x8e, 0x2d, 0xa1,
0xd0, 0xe7, 0xb8, 0x98, 0xad, 0x46, 0xd5, 0xf3, 0xfc, 0x58, 0x99, 0xb8, 0xa7, 0xa2, 0x9c, 0xfa, 0xc7, 0x71, 0x31, 0x5b, 0x8d, 0xca, 0xa7, 0xd9, 0x91, 0x32, 0x71, 0x4f, 0x45, 0x31, 0xf5, 0xdb,
0xed, 0x63, 0xce, 0x81, 0xcd, 0xf8, 0xe2, 0x18, 0x92, 0x20, 0x86, 0xf4, 0x2e, 0x74, 0x04, 0x7d, 0xc7, 0x9c, 0x03, 0x9b, 0xd1, 0xf9, 0x31, 0xc4, 0x41, 0x0c, 0xc9, 0x6d, 0x68, 0x0b, 0xfa, 0xea,
0xf5, 0x86, 0x2d, 0x6a, 0xc3, 0x81, 0x6b, 0x43, 0xfa, 0x3c, 0x71, 0x77, 0xc7, 0xfe, 0x03, 0x3d, 0x0d, 0x9a, 0xd4, 0x86, 0x7d, 0xd7, 0x86, 0xf4, 0x79, 0xe2, 0xee, 0x8e, 0x7d, 0x06, 0x5d, 0x8e,
0x8e, 0x27, 0xa3, 0xea, 0x85, 0x2c, 0xf5, 0x7a, 0xa0, 0x89, 0x0b, 0x94, 0xed, 0xd7, 0xcc, 0x48, 0xc7, 0xa3, 0xf2, 0x99, 0x2c, 0xf4, 0x7a, 0xa0, 0xb1, 0x0b, 0x94, 0xed, 0x55, 0xcc, 0x48, 0xe9,
0xe9, 0xf3, 0x86, 0x82, 0x03, 0x8c, 0xaa, 0x67, 0xa2, 0x9c, 0xd2, 0x6f, 0x0c, 0x73, 0x51, 0x4e, 0xd3, 0x86, 0x62, 0x08, 0x97, 0xe9, 0x47, 0x2f, 0x73, 0xb5, 0xc0, 0xfc, 0x5b, 0x44, 0x93, 0xaf,
0xb1, 0xf4, 0xcd, 0x6c, 0x51, 0xe3, 0x30, 0x0e, 0x1c, 0x06, 0x0b, 0x21, 0xd9, 0x4e, 0x9a, 0x85, 0x85, 0x07, 0xce, 0x41, 0x2d, 0x60, 0x1c, 0x60, 0x54, 0x3e, 0x11, 0xc5, 0x94, 0x7c, 0x98, 0x48,
0xc0, 0xfe, 0x6f, 0xbe, 0x11, 0x75, 0x8a, 0xca, 0xf4, 0x81, 0xe9, 0x2a, 0x3a, 0x9e, 0x61, 0x13, 0x45, 0x31, 0xc5, 0xc2, 0x37, 0xbf, 0x45, 0x35, 0xc1, 0x28, 0x20, 0x18, 0x2c, 0x90, 0x78, 0x3b,
0x68, 0x71, 0xaf, 0xc2, 0x76, 0x4c, 0x4d, 0x33, 0x94, 0x0b, 0xfd, 0x42, 0x4d, 0xce, 0xcd, 0xc6, 0xae, 0x17, 0x08, 0xfb, 0xd2, 0x7c, 0x53, 0xaa, 0x94, 0x16, 0xc9, 0x3d, 0xd3, 0x85, 0x74, 0x3c,
0x35, 0x48, 0x66, 0x6a, 0xe2, 0x06, 0xc3, 0x1c, 0x99, 0x30, 0x8d, 0x49, 0xfa, 0xe7, 0x94, 0xef, 0xc5, 0x3e, 0xd0, 0xe2, 0x5e, 0x85, 0x0d, 0x4d, 0x0f, 0xa4, 0x28, 0x17, 0xfa, 0x99, 0x9a, 0x9c,
0x40, 0x7c, 0xf8, 0x96, 0x86, 0xaf, 0xbf, 0xf7, 0x2f, 0xe7, 0xf3, 0x10, 0x57, 0x6f, 0xc5, 0x6c, 0x99, 0xa5, 0x2b, 0x10, 0xcf, 0xd4, 0xc4, 0x0d, 0x92, 0x39, 0x32, 0x61, 0x1a, 0x99, 0xf4, 0xcf,
0x89, 0x3c, 0x3e, 0x7c, 0x9b, 0xfe, 0x17, 0x5a, 0x33, 0x35, 0x29, 0x89, 0x7f, 0x7f, 0x6f, 0xb3, 0x28, 0xdf, 0x82, 0xe8, 0xe0, 0x0d, 0x0d, 0x6b, 0x6f, 0xf7, 0x7f, 0xce, 0xe7, 0x01, 0xae, 0xde,
0xa6, 0xe5, 0xdd, 0x73, 0xba, 0x66, 0x07, 0x26, 0xb3, 0x24, 0x3b, 0x10, 0x5a, 0x9c, 0x73, 0xf3, 0x88, 0xd9, 0x12, 0x79, 0x74, 0xf0, 0x26, 0xf9, 0x1c, 0x9a, 0x33, 0x35, 0x29, 0x88, 0x7f, 0x6f,
0x99, 0x56, 0xfe, 0x88, 0xa0, 0x3b, 0xaa, 0x38, 0x96, 0xcb, 0x99, 0x0e, 0x7a, 0x24, 0xba, 0xb8, 0x77, 0xb3, 0xa2, 0xe5, 0xdd, 0x73, 0xba, 0x66, 0xfb, 0xa6, 0x12, 0x24, 0xdb, 0x17, 0x5a, 0x9c,
0x47, 0x6c, 0xa7, 0xba, 0x1e, 0x61, 0xd4, 0x84, 0x76, 0x6b, 0x5f, 0x54, 0x4a, 0xf3, 0xe5, 0x7d, 0x71, 0xf3, 0x89, 0x56, 0xfe, 0x6a, 0x40, 0x67, 0x54, 0x72, 0x2c, 0x96, 0x33, 0x1d, 0xf4, 0x54,
0x08, 0xfd, 0xc2, 0xba, 0x1c, 0x0b, 0xf7, 0x88, 0x08, 0x33, 0x5d, 0xd3, 0xe7, 0xa1, 0x9a, 0x99, 0xe3, 0xfc, 0x9e, 0xb2, 0x9d, 0xed, 0x7a, 0x8a, 0x51, 0xd3, 0xda, 0x2d, 0x7f, 0x5e, 0xe9, 0xcd,
0x8e, 0xa3, 0x99, 0xca, 0x3e, 0x68, 0x39, 0xf7, 0x7b, 0xbd, 0x11, 0x98, 0xa5, 0x6d, 0x3d, 0xd0, 0x97, 0xfa, 0x3e, 0xf4, 0x72, 0xeb, 0x72, 0x2c, 0xdc, 0xa3, 0x23, 0xcc, 0x74, 0x45, 0x9f, 0x87,
0x1b, 0xa1, 0x43, 0x43, 0x10, 0x48, 0xd8, 0xef, 0x31, 0x6c, 0x06, 0x3c, 0x0e, 0x50, 0x0b, 0x39, 0x6a, 0xa6, 0x3b, 0x0e, 0x67, 0x2a, 0x7d, 0xaf, 0xe5, 0xdc, 0x7f, 0x07, 0x6a, 0x81, 0x59, 0xf2,
0x73, 0x6c, 0xa3, 0x4f, 0xb2, 0x7d, 0x40, 0xdb, 0xc9, 0xd0, 0xa0, 0x48, 0x2f, 0x66, 0xea, 0x55, 0xd6, 0x03, 0xbd, 0x29, 0xda, 0x34, 0x34, 0x81, 0x84, 0xfd, 0x19, 0xc1, 0x66, 0xc0, 0x63, 0x1f,
0x68, 0x23, 0x16, 0x4a, 0x1d, 0xdb, 0x1c, 0x9b, 0x8d, 0x48, 0x28, 0xc8, 0x62, 0xeb, 0xe2, 0x2c, 0xb5, 0x90, 0x33, 0xc7, 0xb6, 0xf1, 0x51, 0xb6, 0xf7, 0x68, 0x9b, 0x19, 0x1a, 0x14, 0xe9, 0xf9,
0xb6, 0xc3, 0x49, 0x5b, 0x8b, 0xb5, 0x73, 0x36, 0xd6, 0xe6, 0x9d, 0xb6, 0xb1, 0xf6, 0x4e, 0xbb, 0x4c, 0xbd, 0x0a, 0x6d, 0xd0, 0x5c, 0xa9, 0x23, 0x9b, 0x63, 0xb3, 0x41, 0x09, 0x05, 0x59, 0x6c,
0x09, 0xdd, 0xe3, 0x42, 0xcd, 0x69, 0xe3, 0xb9, 0x57, 0x92, 0xc7, 0x67, 0xf2, 0xd3, 0x3b, 0x9b, 0x9e, 0x9f, 0xc5, 0x56, 0x38, 0x99, 0x6b, 0xb1, 0xb6, 0x4f, 0xc7, 0x5a, 0xbf, 0xeb, 0x36, 0xd6,
0x9f, 0x60, 0xb6, 0xe1, 0x13, 0xb3, 0xfd, 0x25, 0xa4, 0xe7, 0x92, 0x58, 0xa6, 0xf7, 0xc3, 0xf9, 0xde, 0x75, 0xd7, 0xa1, 0x73, 0x94, 0xab, 0x39, 0x6d, 0x48, 0xf7, 0xaa, 0xf2, 0xf8, 0x54, 0x7e,
0x1d, 0x9e, 0x4f, 0xa3, 0xd5, 0xb3, 0x53, 0xbc, 0x0d, 0x5d, 0xb7, 0x9c, 0x69, 0x56, 0x0d, 0x37, 0xba, 0xa7, 0xf3, 0x13, 0xec, 0x02, 0xf8, 0xc8, 0x2e, 0xf8, 0x1a, 0x92, 0x33, 0x49, 0x2c, 0x92,
0xff, 0x5e, 0xb2, 0x80, 0xed, 0xc2, 0x0d, 0x8e, 0x27, 0x07, 0x98, 0xa9, 0x31, 0xbd, 0xdc, 0x82, 0xbb, 0xe1, 0xbc, 0x0f, 0xce, 0xa6, 0xd1, 0xea, 0xd9, 0xa9, 0xdf, 0x86, 0x8e, 0x5b, 0xe6, 0x34,
0xb7, 0xc4, 0x85, 0xaf, 0x23, 0xf6, 0x3f, 0xe8, 0xbd, 0x29, 0xb1, 0xa0, 0xa7, 0x1e, 0xa9, 0xa8, 0xab, 0x86, 0x9b, 0x7f, 0x5f, 0x59, 0xc0, 0x76, 0xe0, 0x1a, 0xc7, 0xe3, 0x7d, 0x4c, 0xd5, 0x98,
0x85, 0xcc, 0x6a, 0x15, 0x03, 0xcc, 0xd7, 0x22, 0x53, 0xb9, 0x46, 0xb7, 0x17, 0x7a, 0xdc, 0x43, 0x5e, 0x7a, 0xc1, 0xdb, 0xe3, 0xdc, 0xd7, 0x14, 0xfb, 0x02, 0xba, 0xaf, 0x0b, 0xcc, 0xe9, 0x69,
0xf6, 0x3d, 0xf4, 0xdf, 0x2c, 0x26, 0x85, 0x18, 0xe3, 0x4b, 0xd4, 0xc2, 0xa4, 0x90, 0x2a, 0x20, 0x48, 0x2a, 0x6a, 0x21, 0xd3, 0x4a, 0xc5, 0x00, 0xf3, 0x75, 0x49, 0x55, 0xa6, 0xd1, 0xed, 0x85,
0xf3, 0x09, 0x59, 0xe8, 0xf2, 0x1a, 0x1b, 0x23, 0xa7, 0x58, 0x94, 0x7e, 0x39, 0xf7, 0xb8, 0x87, 0x2e, 0xf7, 0x90, 0xfd, 0x08, 0xbd, 0xd7, 0x8b, 0x49, 0x2e, 0xc6, 0xf8, 0x1c, 0xb5, 0x30, 0x29,
0x97, 0xad, 0xe6, 0xc7, 0x77, 0xbe, 0xfb, 0xf7, 0x44, 0xea, 0xe9, 0xf2, 0x68, 0x27, 0x53, 0xf3, 0xa4, 0x0a, 0xc8, 0x6c, 0x42, 0x16, 0x3a, 0xbc, 0xc2, 0xc6, 0xc8, 0x09, 0xe6, 0x85, 0x5f, 0xe6,
0xdd, 0xfd, 0xfd, 0x2c, 0xdf, 0xcd, 0xa6, 0x42, 0xe6, 0xfb, 0xfb, 0xbb, 0x94, 0xa4, 0xa3, 0x0e, 0x5d, 0xee, 0xe1, 0x45, 0xab, 0xfc, 0xe1, 0xad, 0x1f, 0xfe, 0x3f, 0x91, 0x7a, 0xba, 0x3c, 0x1c,
0xfd, 0x6b, 0xdb, 0xff, 0x2b, 0x00, 0x00, 0xff, 0xff, 0xc9, 0xbd, 0xf6, 0x73, 0xdf, 0x0d, 0x00, 0xa6, 0x6a, 0xbe, 0xb3, 0xb7, 0x97, 0x66, 0x3b, 0xe9, 0x54, 0xc8, 0x6c, 0x6f, 0x6f, 0x87, 0x92,
0x00, 0x74, 0xd8, 0xa6, 0x7f, 0x79, 0x7b, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0xf0, 0xd8, 0xd1, 0xa5,
0x0f, 0x0e, 0x00, 0x00,
} }
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