Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
plugin
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
link33
plugin
Commits
c5d585c4
Commit
c5d585c4
authored
Mar 14, 2019
by
陈德海
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
mempool add get proper fee
parent
9d75053f
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
34 changed files
with
364 additions
and
37 deletions
+364
-37
chain33.toml
chain33.toml
+1
-1
cache.go
plugin/mempool/price/cache.go
+20
-0
cache_test.go
plugin/mempool/price/cache_test.go
+12
-2
chain33.test.toml
plugin/mempool/price/chain33.test.toml
+1
-1
mempool.go
plugin/mempool/price/mempool.go
+4
-0
cache.go
plugin/mempool/score/cache.go
+26
-1
cache_test.go
plugin/mempool/score/cache_test.go
+25
-9
chain33.test.toml
plugin/mempool/score/chain33.test.toml
+1
-1
mempool.go
plugin/mempool/score/mempool.go
+4
-0
mock_mempool_test.go
vendor/github.com/33cn/chain33/client/mock_mempool_test.go
+2
-0
api.go
vendor/github.com/33cn/chain33/client/mocks/api.go
+23
-0
queueprotocol.go
vendor/github.com/33cn/chain33/client/queueprotocol.go
+13
-0
queueprotocol_test.go
vendor/github.com/33cn/chain33/client/queueprotocol_test.go
+27
-0
queueprotocolapi.go
vendor/github.com/33cn/chain33/client/queueprotocolapi.go
+2
-0
rpc_ctx_test.go
vendor/github.com/33cn/chain33/client/rpc_ctx_test.go
+6
-0
grpchandler.go
vendor/github.com/33cn/chain33/rpc/grpchandler.go
+5
-0
grpchandler_test.go
vendor/github.com/33cn/chain33/rpc/grpchandler_test.go
+12
-0
jrpchandler.go
vendor/github.com/33cn/chain33/rpc/jrpchandler.go
+12
-0
jrpchandler_test.go
vendor/github.com/33cn/chain33/rpc/jrpchandler_test.go
+17
-0
types.go
vendor/github.com/33cn/chain33/rpc/types/types.go
+5
-0
mempool.go
...r/github.com/33cn/chain33/system/dapp/commands/mempool.go
+19
-0
cache.go
vendor/github.com/33cn/chain33/system/mempool/cache.go
+1
-0
eventprocess.go
...or/github.com/33cn/chain33/system/mempool/eventprocess.go
+10
-0
mempool_test.go
...or/github.com/33cn/chain33/system/mempool/mempool_test.go
+37
-3
simplequeue.go
vendor/github.com/33cn/chain33/system/mempool/simplequeue.go
+16
-6
simplequeue_test.go
...ithub.com/33cn/chain33/system/mempool/simplequeue_test.go
+7
-2
timeline.go
...thub.com/33cn/chain33/system/mempool/timeline/timeline.go
+5
-6
cfg.go
vendor/github.com/33cn/chain33/types/cfg.go
+5
-5
event.go
vendor/github.com/33cn/chain33/types/event.go
+9
-0
chain33client.go
vendor/github.com/33cn/chain33/types/mocks/chain33client.go
+30
-0
rpc.proto
vendor/github.com/33cn/chain33/types/proto/rpc.proto
+3
-0
transaction.proto
vendor/github.com/33cn/chain33/types/proto/transaction.proto
+4
-0
rpc.pb.go
vendor/github.com/33cn/chain33/types/rpc.pb.go
+0
-0
transaction.pb.go
vendor/github.com/33cn/chain33/types/transaction.pb.go
+0
-0
No files found.
chain33.toml
View file @
c5d585c4
...
...
@@ -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]
...
...
plugin/mempool/price/cache.go
View file @
c5d585c4
...
...
@@ -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
}
plugin/mempool/price/cache_test.go
View file @
c5d585c4
...
...
@@ -113,9 +113,9 @@ func TestTimeCompetition(t *testing.T) {
func
TestPriceCompetition
(
t
*
testing
.
T
)
{
cache
:=
initEnv
(
1
)
cache
.
Push
(
item
1
)
cache
.
Push
(
item
3
)
cache
.
Push
(
item4
)
assert
.
Equal
(
t
,
false
,
cache
.
Exist
(
string
(
item
1
.
Value
.
Hash
())))
assert
.
Equal
(
t
,
false
,
cache
.
Exist
(
string
(
item
3
.
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
())
}
plugin/mempool/price/chain33.test.toml
View file @
c5d585c4
...
...
@@ -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]
...
...
plugin/mempool/price/mempool.go
View file @
c5d585c4
...
...
@@ -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
}
plugin/mempool/score/cache.go
View file @
c5d585c4
...
...
@@ -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
}
plugin/mempool/score/cache_test.go
View file @
c5d585c4
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
:
100000
0
,
Expire
:
1
,
To
:
toAddr
}
tx2
=
&
types
.
Transaction
{
Execer
:
[]
byte
(
"coins"
),
Payload
:
types
.
Encode
(
transfer
),
Fee
:
100000
0
,
Expire
:
2
,
To
:
toAddr
}
tx3
=
&
types
.
Transaction
{
Execer
:
[]
byte
(
"coins"
),
Payload
:
types
.
Encode
(
transfer
),
Fee
:
100000
0
,
Expire
:
3
,
To
:
toAddr
}
tx4
=
&
types
.
Transaction
{
Execer
:
[]
byte
(
"coins"
),
Payload
:
types
.
Encode
(
transfer
),
Fee
:
200000
0
,
Expire
:
4
,
To
:
toAddr
}
tx5
=
&
types
.
Transaction
{
Execer
:
[]
byte
(
"coins"
),
Payload
:
types
.
Encode
(
transfer
),
Fee
:
100000
0
,
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
(
item
1
)
cache
.
Push
(
item
3
)
cache
.
Push
(
item4
)
assert
.
Equal
(
t
,
false
,
cache
.
Exist
(
string
(
item
1
.
Value
.
Hash
())))
assert
.
Equal
(
t
,
false
,
cache
.
Exist
(
string
(
item
3
.
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
())
}
plugin/mempool/score/chain33.test.toml
View file @
c5d585c4
...
...
@@ -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]
...
...
plugin/mempool/score/mempool.go
View file @
c5d585c4
...
...
@@ -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
}
vendor/github.com/33cn/chain33/client/mock_mempool_test.go
View file @
c5d585c4
...
...
@@ -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
)
}
...
...
vendor/github.com/33cn/chain33/client/mocks/api.go
View file @
c5d585c4
...
...
@@ -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
()
...
...
vendor/github.com/33cn/chain33/client/queueprotocol.go
View file @
c5d585c4
...
...
@@ -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
{
...
...
vendor/github.com/33cn/chain33/client/queueprotocol_test.go
View file @
c5d585c4
...
...
@@ -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
)
...
...
vendor/github.com/33cn/chain33/client/queueprotocolapi.go
View file @
c5d585c4
...
...
@@ -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
)
...
...
vendor/github.com/33cn/chain33/client/rpc_ctx_test.go
View file @
c5d585c4
...
...
@@ -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
{
...
...
vendor/github.com/33cn/chain33/rpc/grpchandler.go
View file @
c5d585c4
...
...
@@ -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
)
{
...
...
vendor/github.com/33cn/chain33/rpc/grpchandler_test.go
View file @
c5d585c4
...
...
@@ -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")
...
...
vendor/github.com/33cn/chain33/rpc/jrpchandler.go
View file @
c5d585c4
...
...
@@ -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
{
...
...
vendor/github.com/33cn/chain33/rpc/jrpchandler_test.go
View file @
c5d585c4
...
...
@@ -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
)
...
...
vendor/github.com/33cn/chain33/rpc/types/types.go
View file @
c5d585c4
...
...
@@ -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"`
...
...
vendor/github.com/33cn/chain33/system/dapp/commands/mempool.go
View file @
c5d585c4
...
...
@@ -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
()
}
vendor/github.com/33cn/chain33/system/mempool/cache.go
View file @
c5d585c4
...
...
@@ -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中包装交易的数据结构
...
...
vendor/github.com/33cn/chain33/system/mempool/eventprocess.go
View file @
c5d585c4
...
...
@@ -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
()
{
...
...
vendor/github.com/33cn/chain33/system/mempool/mempool_test.go
View file @
c5d585c4
...
...
@@ -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
(
s
ize
))
mem
.
SetQueueCache
(
NewSimpleQueue
(
s
ubConfig
))
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
(
s
ize
))
mem
.
SetQueueCache
(
NewSimpleQueue
(
s
ubConfig
))
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
()
...
...
vendor/github.com/33cn/chain33/system/mempool/simplequeue.go
View file @
c5d585c4
...
...
@@ -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
}
vendor/github.com/33cn/chain33/system/mempool/simplequeue_test.go
View file @
c5d585c4
...
...
@@ -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
())
}
vendor/github.com/33cn/chain33/system/mempool/timeline/timeline.go
View file @
c5d585c4
...
...
@@ -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
s
ubConfig
var
subcfg
drivers
.
S
ubConfig
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
}
vendor/github.com/33cn/chain33/types/cfg.go
View file @
c5d585c4
...
...
@@ -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 配置
...
...
vendor/github.com/33cn/chain33/types/event.go
View file @
c5d585c4
...
...
@@ -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"
,
}
vendor/github.com/33cn/chain33/types/mocks/chain33client.go
View file @
c5d585c4
...
...
@@ -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
))
...
...
vendor/github.com/33cn/chain33/types/proto/rpc.proto
View file @
c5d585c4
...
...
@@ -76,6 +76,9 @@ service chain33 {
//获取最新的Mempool
rpc
GetLastMemPool
(
ReqNil
)
returns
(
ReplyTxList
)
{}
//获取最新的ProperFee
rpc
GetProperFee
(
ReqNil
)
returns
(
ReplyProperFee
)
{}
// 获取钱包状态
rpc
GetWalletStatus
(
ReqNil
)
returns
(
WalletStatus
)
{}
//区块浏览器接口
...
...
vendor/github.com/33cn/chain33/types/proto/transaction.proto
View file @
c5d585c4
...
...
@@ -171,6 +171,10 @@ message ReplyTxList {
repeated
Transaction
txs
=
1
;
}
message
ReplyProperFee
{
int64
properFee
=
1
;
}
message
TxHashList
{
repeated
bytes
hashes
=
1
;
int64
count
=
2
;
...
...
vendor/github.com/33cn/chain33/types/rpc.pb.go
View file @
c5d585c4
This diff is collapsed.
Click to expand it.
vendor/github.com/33cn/chain33/types/transaction.pb.go
View file @
c5d585c4
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment