Skip to content

Commit e4319cc

Browse files
authored
Define experimental action and do not process them by default (iotexproject#993)
1 parent a6e545d commit e4319cc

25 files changed

+162
-222
lines changed

action/action.go

+19
Original file line numberDiff line numberDiff line change
@@ -377,3 +377,22 @@ func ClassifyActions(actions []SealedEnvelope) ([]*Transfer, []*Vote, []*Executi
377377
}
378378
return tsfs, votes, exes
379379
}
380+
381+
// IsExperimentalAction test it the action is experimental
382+
func IsExperimentalAction(action Action) bool {
383+
switch action.(type) {
384+
case *StartSubChain:
385+
return true
386+
case *StopSubChain:
387+
return true
388+
case *PutBlock:
389+
return true
390+
case *CreateDeposit:
391+
return true
392+
case *SettleDeposit:
393+
return true
394+
case *Vote:
395+
return true
396+
}
397+
return false
398+
}

action/protocol/execution/protocol_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -320,9 +320,9 @@ func (sct *SmartContractTest) deployContracts(
320320
addr, _ := address.FromString(receipt.ContractAddress)
321321
copy(evmContractAddrHash[:], addr.Bytes())
322322
if contract.AppendContractAddress {
323-
lenOfByteCode:=len(contract.ByteCode())
323+
lenOfByteCode := len(contract.ByteCode())
324324
r.True(bytes.Contains(contract.ByteCode()[:lenOfByteCode-32], stateDB.GetCode(evmContractAddrHash)))
325-
}else{
325+
} else {
326326
r.True(bytes.Contains(sct.Deployments[i].ByteCode(), stateDB.GetCode(evmContractAddrHash)))
327327
}
328328
contractAddresses = append(contractAddresses, receipt.ContractAddress)

action/protocol/multichain/mainchain/protocol_test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,15 @@ func TestAddSubChainActions(t *testing.T) {
3535
config.Default,
3636
blockchain.InMemStateFactoryOption(),
3737
blockchain.InMemDaoOption(),
38+
blockchain.EnableExperimentalActions(),
3839
)
3940
require.NoError(t, bc.Start(ctx))
4041
_, err := bc.CreateState(
4142
testaddress.Addrinfo["producer"].String(),
4243
big.NewInt(0).Mul(big.NewInt(10000000000), big.NewInt(unit.Iotx)),
4344
)
4445
require.NoError(t, err)
45-
ap, err := actpool.NewActPool(bc, cfg.ActPool)
46+
ap, err := actpool.NewActPool(bc, cfg.ActPool, actpool.EnableExperimentalActions())
4647
require.NoError(t, err)
4748
p := NewProtocol(bc)
4849
ap.AddActionValidators(p)

action/protocol/multichain/mainchain/startsubchain_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ func TestNoStartSubChainInGenesis(t *testing.T) {
328328
cfg,
329329
blockchain.InMemStateFactoryOption(),
330330
blockchain.InMemDaoOption(),
331+
blockchain.EnableExperimentalActions(),
331332
)
332333
p := NewProtocol(bc)
333334
bc.GetFactory().AddActionHandlers(p)
@@ -352,6 +353,7 @@ func TestStartSubChainInGenesis(t *testing.T) {
352353
blockchain.InMemStateFactoryOption(),
353354
blockchain.InMemDaoOption(),
354355
blockchain.RegistryOption(&registry),
356+
blockchain.EnableExperimentalActions(),
355357
)
356358
vp := vote.NewProtocol(bc)
357359
registry.Register(vote.ProtocolID, vp)

action/protocol/multichain/subchain/protocol_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ func TestMutateDeposit(t *testing.T) {
9797
config.Default,
9898
blockchain.InMemStateFactoryOption(),
9999
blockchain.InMemDaoOption(),
100+
blockchain.EnableExperimentalActions(),
100101
)
101102
require.NoError(t, bc.Start(ctx))
102103
exp := mock_explorer.NewMockExplorer(ctrl)

actpool/actpool.go

+30-10
Original file line numberDiff line numberDiff line change
@@ -51,21 +51,33 @@ type ActPool interface {
5151
AddActionEnvelopeValidators(...protocol.ActionEnvelopeValidator)
5252
}
5353

54+
// Option sets action pool construction parameter
55+
type Option func(pool *actPool) error
56+
57+
// EnableExperimentalActions enables the action pool to take experimental actions
58+
func EnableExperimentalActions() Option {
59+
return func(pool *actPool) error {
60+
pool.enableExperimentalActions = true
61+
return nil
62+
}
63+
}
64+
5465
// actPool implements ActPool interface
5566
type actPool struct {
56-
mutex sync.RWMutex
57-
cfg config.ActPool
58-
bc blockchain.Blockchain
59-
accountActs map[string]ActQueue
60-
allActions map[hash.Hash256]action.SealedEnvelope
61-
gasInPool uint64
62-
actionEnvelopeValidators []protocol.ActionEnvelopeValidator
63-
validators []protocol.ActionValidator
64-
timerFactory *prometheustimer.TimerFactory
67+
mutex sync.RWMutex
68+
cfg config.ActPool
69+
bc blockchain.Blockchain
70+
accountActs map[string]ActQueue
71+
allActions map[hash.Hash256]action.SealedEnvelope
72+
gasInPool uint64
73+
actionEnvelopeValidators []protocol.ActionEnvelopeValidator
74+
validators []protocol.ActionValidator
75+
timerFactory *prometheustimer.TimerFactory
76+
enableExperimentalActions bool
6577
}
6678

6779
// NewActPool constructs a new actpool
68-
func NewActPool(bc blockchain.Blockchain, cfg config.ActPool) (ActPool, error) {
80+
func NewActPool(bc blockchain.Blockchain, cfg config.ActPool, opts ...Option) (ActPool, error) {
6981
if bc == nil {
7082
return nil, errors.New("Try to attach a nil blockchain")
7183
}
@@ -75,6 +87,11 @@ func NewActPool(bc blockchain.Blockchain, cfg config.ActPool) (ActPool, error) {
7587
accountActs: make(map[string]ActQueue),
7688
allActions: make(map[hash.Hash256]action.SealedEnvelope),
7789
}
90+
for _, opt := range opts {
91+
if err := opt(ap); err != nil {
92+
return nil, err
93+
}
94+
}
7895
timerFactory, err := prometheustimer.New(
7996
"iotex_action_pool_perf",
8097
"Performance of action pool",
@@ -130,6 +147,9 @@ func (ap *actPool) PendingActionMap() map[string][]action.SealedEnvelope {
130147
func (ap *actPool) Add(act action.SealedEnvelope) error {
131148
ap.mutex.Lock()
132149
defer ap.mutex.Unlock()
150+
if !ap.enableExperimentalActions && action.IsExperimentalAction(act.Action()) {
151+
return errors.New("Experimental action is not enabled")
152+
}
133153
// Reject action if pool space is full
134154
if uint64(len(ap.allActions)) >= ap.cfg.MaxNumActsPerPool {
135155
return errors.Wrap(action.ErrActPool, "insufficient space for action")

actpool/actpool_test.go

+27-21
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ import (
3333
)
3434

3535
const (
36-
maxNumActsPerPool = 8192
36+
maxNumActsPerPool = 8192
3737
maxGasLimitPerPool = 81920000
38-
maxNumActsPerAcct = 256
38+
maxNumActsPerAcct = 256
3939
)
4040

4141
var (
@@ -66,7 +66,7 @@ func TestActPool_validateGenericAction(t *testing.T) {
6666
_, err := bc.CreateState(addr1, big.NewInt(100))
6767
require.NoError(err)
6868
apConfig := getActPoolCfg()
69-
Ap, err := NewActPool(bc, apConfig)
69+
Ap, err := NewActPool(bc, apConfig, EnableExperimentalActions())
7070
require.NoError(err)
7171
ap, ok := Ap.(*actPool)
7272
require.True(ok)
@@ -132,6 +132,7 @@ func TestActPool_AddActs(t *testing.T) {
132132
config.Default,
133133
blockchain.InMemStateFactoryOption(),
134134
blockchain.InMemDaoOption(),
135+
blockchain.EnableExperimentalActions(),
135136
)
136137
require.NoError(bc.Start(context.Background()))
137138
_, err := bc.CreateState(addr1, big.NewInt(100))
@@ -140,7 +141,7 @@ func TestActPool_AddActs(t *testing.T) {
140141
require.NoError(err)
141142
// Create actpool
142143
apConfig := getActPoolCfg()
143-
Ap, err := NewActPool(bc, apConfig)
144+
Ap, err := NewActPool(bc, apConfig, EnableExperimentalActions())
144145
require.NoError(err)
145146
ap, ok := Ap.(*actPool)
146147
require.True(ok)
@@ -208,7 +209,7 @@ func TestActPool_AddActs(t *testing.T) {
208209
require.Error(err)
209210
// Case II: Pool space/gas space is full
210211
mockBC := mock_blockchain.NewMockBlockchain(ctrl)
211-
Ap2, err := NewActPool(mockBC, apConfig)
212+
Ap2, err := NewActPool(mockBC, apConfig, EnableExperimentalActions())
212213
require.NoError(err)
213214
ap2, ok := Ap2.(*actPool)
214215
require.True(ok)
@@ -227,15 +228,15 @@ func TestActPool_AddActs(t *testing.T) {
227228
require.NoError(err)
228229
ap3, ok := Ap3.(*actPool)
229230
require.True(ok)
230-
for i := uint64(1); i < apConfig.MaxGasLimitPerPool / 10000; i++ {
231+
for i := uint64(1); i < apConfig.MaxGasLimitPerPool/10000; i++ {
231232
nTsf, err := testutil.SignedTransfer(addr2, priKey2, i, big.NewInt(50), nil, uint64(10000), big.NewInt(0))
232233
require.NoError(err)
233234
ap3.allActions[nTsf.Hash()] = nTsf
234235
intrinsicGas, err := nTsf.IntrinsicGas()
235236
require.NoError(err)
236237
ap3.gasInPool += intrinsicGas
237238
}
238-
tsf10, err := testutil.SignedTransfer(addr2, priKey2, uint64(apConfig.MaxGasLimitPerPool / 10000), big.NewInt(50), []byte{1,2,3}, uint64(20000), big.NewInt(0))
239+
tsf10, err := testutil.SignedTransfer(addr2, priKey2, uint64(apConfig.MaxGasLimitPerPool/10000), big.NewInt(50), []byte{1, 2, 3}, uint64(20000), big.NewInt(0))
239240
require.NoError(err)
240241
err = ap3.Add(tsf10)
241242
require.True(strings.Contains(err.Error(), "insufficient gas space for action"))
@@ -327,7 +328,7 @@ func TestActPool_PickActs(t *testing.T) {
327328
_, err = bc.CreateState(addr2, big.NewInt(10))
328329
require.NoError(err)
329330
// Create actpool
330-
Ap, err := NewActPool(bc, cfg)
331+
Ap, err := NewActPool(bc, cfg, EnableExperimentalActions())
331332
require.NoError(err)
332333
ap, ok := Ap.(*actPool)
333334
require.True(ok)
@@ -402,14 +403,15 @@ func TestActPool_removeConfirmedActs(t *testing.T) {
402403
config.Default,
403404
blockchain.InMemStateFactoryOption(),
404405
blockchain.InMemDaoOption(),
406+
blockchain.EnableExperimentalActions(),
405407
)
406408
bc.GetFactory().AddActionHandlers(account.NewProtocol(), vote.NewProtocol(bc))
407409
require.NoError(bc.Start(context.Background()))
408410
_, err := bc.CreateState(addr1, big.NewInt(100))
409411
require.NoError(err)
410412
// Create actpool
411413
apConfig := getActPoolCfg()
412-
Ap, err := NewActPool(bc, apConfig)
414+
Ap, err := NewActPool(bc, apConfig, EnableExperimentalActions())
413415
require.NoError(err)
414416
ap, ok := Ap.(*actPool)
415417
require.True(ok)
@@ -471,14 +473,14 @@ func TestActPool_Reset(t *testing.T) {
471473
require.NoError(err)
472474

473475
apConfig := getActPoolCfg()
474-
Ap1, err := NewActPool(bc, apConfig)
476+
Ap1, err := NewActPool(bc, apConfig, EnableExperimentalActions())
475477
require.NoError(err)
476478
ap1, ok := Ap1.(*actPool)
477479
require.True(ok)
478480
ap1.AddActionEnvelopeValidators(protocol.NewGenericValidator(bc, genesis.Default.ActionGasLimit))
479481
ap1.AddActionValidators(account.NewProtocol(), vote.NewProtocol(bc),
480482
execution.NewProtocol(bc))
481-
Ap2, err := NewActPool(bc, apConfig)
483+
Ap2, err := NewActPool(bc, apConfig, EnableExperimentalActions())
482484
require.NoError(err)
483485
ap2, ok := Ap2.(*actPool)
484486
require.True(ok)
@@ -843,13 +845,14 @@ func TestActPool_removeInvalidActs(t *testing.T) {
843845
config.Default,
844846
blockchain.InMemStateFactoryOption(),
845847
blockchain.InMemDaoOption(),
848+
blockchain.EnableExperimentalActions(),
846849
)
847850
require.NoError(bc.Start(context.Background()))
848851
_, err := bc.CreateState(addr1, big.NewInt(100))
849852
require.NoError(err)
850853
// Create actpool
851854
apConfig := getActPoolCfg()
852-
Ap, err := NewActPool(bc, apConfig)
855+
Ap, err := NewActPool(bc, apConfig, EnableExperimentalActions())
853856
require.NoError(err)
854857
ap, ok := Ap.(*actPool)
855858
require.True(ok)
@@ -890,6 +893,7 @@ func TestActPool_GetPendingNonce(t *testing.T) {
890893
config.Default,
891894
blockchain.InMemStateFactoryOption(),
892895
blockchain.InMemDaoOption(),
896+
blockchain.EnableExperimentalActions(),
893897
)
894898
require.NoError(bc.Start(context.Background()))
895899
_, err := bc.CreateState(addr1, big.NewInt(100))
@@ -898,7 +902,7 @@ func TestActPool_GetPendingNonce(t *testing.T) {
898902
require.NoError(err)
899903
// Create actpool
900904
apConfig := getActPoolCfg()
901-
Ap, err := NewActPool(bc, apConfig)
905+
Ap, err := NewActPool(bc, apConfig, EnableExperimentalActions())
902906
require.NoError(err)
903907
ap, ok := Ap.(*actPool)
904908
require.True(ok)
@@ -942,7 +946,7 @@ func TestActPool_GetUnconfirmedActs(t *testing.T) {
942946
require.NoError(err)
943947
// Create actpool
944948
apConfig := getActPoolCfg()
945-
Ap, err := NewActPool(bc, apConfig)
949+
Ap, err := NewActPool(bc, apConfig, EnableExperimentalActions())
946950
require.NoError(err)
947951
ap, ok := Ap.(*actPool)
948952
require.True(ok)
@@ -984,7 +988,7 @@ func TestActPool_GetActionByHash(t *testing.T) {
984988
require.NoError(err)
985989
// Create actpool
986990
apConfig := getActPoolCfg()
987-
Ap, err := NewActPool(bc, apConfig)
991+
Ap, err := NewActPool(bc, apConfig, EnableExperimentalActions())
988992
require.NoError(err)
989993
ap, ok := Ap.(*actPool)
990994
require.True(ok)
@@ -1015,7 +1019,7 @@ func TestActPool_GetCapacity(t *testing.T) {
10151019
bc := blockchain.NewBlockchain(config.Default, blockchain.InMemStateFactoryOption(), blockchain.InMemDaoOption())
10161020
// Create actpool
10171021
apConfig := getActPoolCfg()
1018-
Ap, err := NewActPool(bc, apConfig)
1022+
Ap, err := NewActPool(bc, apConfig, EnableExperimentalActions())
10191023
require.NoError(err)
10201024
ap, ok := Ap.(*actPool)
10211025
require.True(ok)
@@ -1029,14 +1033,15 @@ func TestActPool_GetSize(t *testing.T) {
10291033
config.Default,
10301034
blockchain.InMemStateFactoryOption(),
10311035
blockchain.InMemDaoOption(),
1036+
blockchain.EnableExperimentalActions(),
10321037
)
10331038
bc.GetFactory().AddActionHandlers(account.NewProtocol(), vote.NewProtocol(bc))
10341039
require.NoError(bc.Start(context.Background()))
10351040
_, err := bc.CreateState(addr1, big.NewInt(100))
10361041
require.NoError(err)
10371042
// Create actpool
10381043
apConfig := getActPoolCfg()
1039-
Ap, err := NewActPool(bc, apConfig)
1044+
Ap, err := NewActPool(bc, apConfig, EnableExperimentalActions())
10401045
require.NoError(err)
10411046
ap, ok := Ap.(*actPool)
10421047
require.True(ok)
@@ -1085,14 +1090,15 @@ func TestActPool_AddActionNotEnoughGasPride(t *testing.T) {
10851090
config.Default,
10861091
blockchain.InMemStateFactoryOption(),
10871092
blockchain.InMemDaoOption(),
1093+
blockchain.EnableExperimentalActions(),
10881094
)
10891095
require.NoError(t, bc.Start(context.Background()))
10901096
defer func() {
10911097
require.NoError(t, bc.Stop(context.Background()))
10921098
}()
10931099

10941100
cfg := config.Default.ActPool
1095-
ap, err := NewActPool(bc, cfg)
1101+
ap, err := NewActPool(bc, cfg, EnableExperimentalActions())
10961102
require.NoError(t, err)
10971103
tsf, err := testutil.SignedTransfer(
10981104
identityset.Address(0).String(),
@@ -1126,10 +1132,10 @@ func (ap *actPool) getPendingBalance(addr string) (*big.Int, error) {
11261132

11271133
func getActPoolCfg() config.ActPool {
11281134
return config.ActPool{
1129-
MaxNumActsPerPool: maxNumActsPerPool,
1135+
MaxNumActsPerPool: maxNumActsPerPool,
11301136
MaxGasLimitPerPool: maxGasLimitPerPool,
1131-
MaxNumActsPerAcct: maxNumActsPerAcct,
1132-
MinGasPriceStr: "0",
1137+
MaxNumActsPerAcct: maxNumActsPerAcct,
1138+
MinGasPriceStr: "0",
11331139
}
11341140
}
11351141

actpool/actqueue_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ func TestActQueuePendingActs(t *testing.T) {
137137
cfg := config.Default
138138
bc := mock_blockchain.NewMockBlockchain(ctrl)
139139
bc.EXPECT().Nonce(gomock.Any()).Return(uint64(1), nil).Times(1)
140-
ap, err := NewActPool(bc, cfg.ActPool)
140+
ap, err := NewActPool(bc, cfg.ActPool, EnableExperimentalActions())
141141
require.NoError(err)
142142
q := NewActQueue(ap.(*actPool), "").(*actQueue)
143143
vote1, err := testutil.SignedVote(addr2, priKey1, 2, 0, big.NewInt(0))

api/api_test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -1291,6 +1291,7 @@ func setupChain(cfg config.Config) (blockchain.Blockchain, *protocol.Registry, e
12911291
blockchain.PrecreatedStateFactoryOption(sf),
12921292
blockchain.InMemDaoOption(),
12931293
blockchain.RegistryOption(&registry),
1294+
blockchain.EnableExperimentalActions(),
12941295
)
12951296
if bc == nil {
12961297
return nil, nil, errors.New("failed to create blockchain")
@@ -1333,7 +1334,7 @@ func setupChain(cfg config.Config) (blockchain.Blockchain, *protocol.Registry, e
13331334
}
13341335

13351336
func setupActPool(bc blockchain.Blockchain, cfg config.ActPool) (actpool.ActPool, error) {
1336-
ap, err := actpool.NewActPool(bc, cfg)
1337+
ap, err := actpool.NewActPool(bc, cfg, actpool.EnableExperimentalActions())
13371338
if err != nil {
13381339
return nil, err
13391340
}

0 commit comments

Comments
 (0)