Skip to content

Commit 0d1f6d6

Browse files
authored
Merge branch 'master' into forkchain
2 parents 3dcf3f2 + e1722d5 commit 0d1f6d6

File tree

9 files changed

+198
-86
lines changed

9 files changed

+198
-86
lines changed

action/protocol/rewarding/protocol.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ func (p *Protocol) CreatePreStates(ctx context.Context, sm protocol.StateManager
111111
return p.migrateValueGreenland(ctx, sm)
112112
case g.KamchatkaBlockHeight:
113113
return p.setFoundationBonusExtension(ctx, sm)
114+
case g.ToBeEnabledBlockHeight: // todo: change to wake block height
115+
return p.SetReward(ctx, sm, g.WakeBlockReward(), true)
114116
}
115117
return nil
116118
}

action/protocol/rewarding/reward_test.go

Lines changed: 83 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -35,56 +35,89 @@ import (
3535
)
3636

3737
func TestProtocol_GrantBlockReward(t *testing.T) {
38-
testProtocol(t, func(t *testing.T, ctx context.Context, sm protocol.StateManager, p *Protocol) {
39-
blkCtx, ok := protocol.GetBlockCtx(ctx)
40-
require.True(t, ok)
41-
42-
// Grant block reward will fail because of no available balance
43-
_, err := p.GrantBlockReward(ctx, sm)
44-
require.Error(t, err)
45-
46-
_, err = p.Deposit(ctx, sm, big.NewInt(200), iotextypes.TransactionLogType_DEPOSIT_TO_REWARDING_FUND)
47-
require.NoError(t, err)
48-
49-
// Grant block reward
50-
rewardLog, err := p.GrantBlockReward(ctx, sm)
51-
require.NoError(t, err)
52-
require.Equal(t, p.addr.String(), rewardLog.Address)
53-
var rl rewardingpb.RewardLog
54-
require.NoError(t, proto.Unmarshal(rewardLog.Data, &rl))
55-
require.Equal(t, rewardingpb.RewardLog_BLOCK_REWARD, rl.Type)
56-
require.Equal(t, "10", rl.Amount)
57-
58-
availableBalance, _, err := p.AvailableBalance(ctx, sm)
59-
require.NoError(t, err)
60-
assert.Equal(t, big.NewInt(190), availableBalance)
61-
// Operator shouldn't get reward
62-
unclaimedBalance, _, err := p.UnclaimedBalance(ctx, sm, blkCtx.Producer)
63-
require.NoError(t, err)
64-
assert.Equal(t, big.NewInt(0), unclaimedBalance)
65-
// Beneficiary should get reward
66-
unclaimedBalance, _, err = p.UnclaimedBalance(ctx, sm, identityset.Address(0))
67-
require.NoError(t, err)
68-
assert.Equal(t, big.NewInt(10), unclaimedBalance)
69-
70-
// Grant the same block reward again will fail
71-
_, err = p.GrantBlockReward(ctx, sm)
72-
require.Error(t, err)
73-
74-
// Grant with priority fee after VanuatuBlockHeight
75-
blkCtx.AccumulatedTips = *big.NewInt(5)
76-
blkCtx.BlockHeight = genesis.TestDefault().VanuatuBlockHeight
77-
ctx = protocol.WithFeatureCtx(protocol.WithBlockCtx(ctx, blkCtx))
78-
rewardLog, err = p.GrantBlockReward(ctx, sm)
79-
require.NoError(t, err)
80-
rls, err := UnmarshalRewardLog(rewardLog.Data)
81-
require.NoError(t, err)
82-
require.Len(t, rls.Logs, 2)
83-
require.Equal(t, rewardingpb.RewardLog_BLOCK_REWARD, rls.Logs[0].Type)
84-
require.Equal(t, "10", rls.Logs[0].Amount)
85-
require.Equal(t, rewardingpb.RewardLog_PRIORITY_BONUS, rls.Logs[1].Type)
86-
require.Equal(t, blkCtx.AccumulatedTips.String(), rls.Logs[1].Amount)
87-
}, false)
38+
req := require.New(t)
39+
for _, tv := range []struct {
40+
blockReward *big.Int
41+
deposit *big.Int
42+
isWakeBlock bool
43+
}{
44+
{big.NewInt(10), big.NewInt(200), false},
45+
{big.NewInt(48), big.NewInt(300), true},
46+
} {
47+
testProtocol(t, func(t *testing.T, ctx context.Context, sm protocol.StateManager, p *Protocol) {
48+
if tv.isWakeBlock {
49+
g := genesis.MustExtractGenesisContext(ctx)
50+
g.WakeBlockRewardStr = tv.blockReward.String()
51+
wakeBlockCtx := genesis.WithGenesisContext(protocol.WithBlockCtx(ctx, protocol.BlockCtx{
52+
BlockHeight: genesis.TestDefault().ToBeEnabledBlockHeight,
53+
}), g)
54+
req.NoError(p.CreatePreStates(wakeBlockCtx, sm))
55+
}
56+
// verify block reward
57+
br, err := p.BlockReward(ctx, sm)
58+
req.NoError(err)
59+
req.Equal(tv.blockReward, br)
60+
// Grant block reward will fail because of no available balance
61+
_, err = p.GrantBlockReward(ctx, sm)
62+
req.Error(err)
63+
64+
_, err = p.Deposit(ctx, sm, tv.deposit, iotextypes.TransactionLogType_DEPOSIT_TO_REWARDING_FUND)
65+
req.NoError(err)
66+
67+
// Grant block reward
68+
rewardLog, err := p.GrantBlockReward(ctx, sm)
69+
req.NoError(err)
70+
req.Equal(p.addr.String(), rewardLog.Address)
71+
var rl rewardingpb.RewardLog
72+
req.NoError(proto.Unmarshal(rewardLog.Data, &rl))
73+
req.Equal(rewardingpb.RewardLog_BLOCK_REWARD, rl.Type)
74+
req.Equal(tv.blockReward.String(), rl.Amount)
75+
76+
availableBalance, _, err := p.AvailableBalance(ctx, sm)
77+
req.NoError(err)
78+
req.Equal(tv.deposit.Sub(tv.deposit, tv.blockReward), availableBalance)
79+
// Operator shouldn't get reward
80+
blkCtx := protocol.MustGetBlockCtx(ctx)
81+
unclaimedBalance, _, err := p.UnclaimedBalance(ctx, sm, blkCtx.Producer)
82+
req.NoError(err)
83+
req.Equal(big.NewInt(0), unclaimedBalance)
84+
// Beneficiary should get reward
85+
unclaimedBalance, _, err = p.UnclaimedBalance(ctx, sm, identityset.Address(0))
86+
req.NoError(err)
87+
req.Equal(tv.blockReward, unclaimedBalance)
88+
89+
// Grant the same block reward again will fail
90+
_, err = p.GrantBlockReward(ctx, sm)
91+
req.Error(err)
92+
93+
// Grant with priority fee after VanuatuBlockHeight
94+
blkCtx.AccumulatedTips = *big.NewInt(5)
95+
blkCtx.BlockHeight = genesis.TestDefault().VanuatuBlockHeight
96+
ctx = protocol.WithFeatureCtx(protocol.WithBlockCtx(ctx, blkCtx))
97+
tLog, err := DepositGas(ctx, sm, nil, protocol.PriorityFeeOption(&blkCtx.AccumulatedTips))
98+
req.NoError(err)
99+
req.Equal(tLog[0].Type, iotextypes.TransactionLogType_PRIORITY_FEE)
100+
req.Equal(&blkCtx.AccumulatedTips, tLog[0].Amount)
101+
rewardLog, err = p.GrantBlockReward(ctx, sm)
102+
req.NoError(err)
103+
rls, err := UnmarshalRewardLog(rewardLog.Data)
104+
req.NoError(err)
105+
req.Len(rls.Logs, 2)
106+
req.Equal(rewardingpb.RewardLog_BLOCK_REWARD, rls.Logs[0].Type)
107+
req.Equal(tv.blockReward.String(), rls.Logs[0].Amount)
108+
req.Equal(rewardingpb.RewardLog_PRIORITY_BONUS, rls.Logs[1].Type)
109+
req.Equal(blkCtx.AccumulatedTips.String(), rls.Logs[1].Amount)
110+
111+
// check available and receiver balance
112+
availableBalance, _, err = p.AvailableBalance(ctx, sm)
113+
req.NoError(err)
114+
req.Equal(tv.deposit.Sub(tv.deposit, tv.blockReward), availableBalance)
115+
unclaimedBalance, _, err = p.UnclaimedBalance(ctx, sm, identityset.Address(0))
116+
req.NoError(err)
117+
tv.blockReward.Lsh(tv.blockReward, 1)
118+
req.Equal(tv.blockReward.Add(tv.blockReward, &blkCtx.AccumulatedTips), unclaimedBalance)
119+
}, false)
120+
}
88121
}
89122

90123
func TestProtocol_GrantEpochReward(t *testing.T) {

blockchain/genesis/genesis.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ func defaultConfig() Genesis {
182182
FoundationBonusP2StartEpoch: 9698,
183183
FoundationBonusP2EndEpoch: 18458,
184184
ProductivityThreshold: 85,
185+
WakeBlockRewardStr: "4800000000000000000",
185186
},
186187
Staking: Staking{
187188
VoteWeightCalConsts: VoteWeightCalConsts{
@@ -448,6 +449,8 @@ type (
448449
FoundationBonusP2EndEpoch uint64 `yaml:"foundationBonusP2EndEpoch"`
449450
// ProductivityThreshold is the percentage number that a delegate's productivity needs to reach not to get probation
450451
ProductivityThreshold uint64 `yaml:"productivityThreshold"`
452+
// WakeBlockReward is the block reward amount starts from wake height in decimal string format
453+
WakeBlockRewardStr string `yaml:"wakeBlockRewardStr"`
451454
}
452455
// Staking contains the configs for staking protocol
453456
Staking struct {
@@ -836,7 +839,7 @@ func (r *Rewarding) EpochReward() *big.Int {
836839
func (r *Rewarding) AleutianEpochReward() *big.Int {
837840
val, ok := new(big.Int).SetString(r.AleutianEpochRewardStr, 10)
838841
if !ok {
839-
log.S().Panicf("Error when casting epoch reward string %s into big int", r.EpochRewardStr)
842+
log.S().Panicf("Error when casting epoch reward string %s into big int", r.AleutianEpochRewardStr)
840843
}
841844
return val
842845
}
@@ -845,7 +848,16 @@ func (r *Rewarding) AleutianEpochReward() *big.Int {
845848
func (r *Rewarding) DardanellesBlockReward() *big.Int {
846849
val, ok := new(big.Int).SetString(r.DardanellesBlockRewardStr, 10)
847850
if !ok {
848-
log.S().Panicf("Error when casting block reward string %s into big int", r.EpochRewardStr)
851+
log.S().Panicf("Error when casting block reward string %s into big int", r.DardanellesBlockRewardStr)
852+
}
853+
return val
854+
}
855+
856+
// WakeBlockReward returns the block reward amount after wake fork
857+
func (r *Rewarding) WakeBlockReward() *big.Int {
858+
val, ok := new(big.Int).SetString(r.WakeBlockRewardStr, 10)
859+
if !ok {
860+
log.S().Panicf("Error when casting block reward string %s into big int", r.WakeBlockRewardStr)
849861
}
850862
return val
851863
}

blockchain/genesis/genesis_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/stretchr/testify/require"
1414

1515
"github.com/iotexproject/iotex-address/address"
16+
"github.com/iotexproject/iotex-core/v2/pkg/unit"
1617
)
1718

1819
func TestDefaultConfig(t *testing.T) {
@@ -142,3 +143,14 @@ func TestDeployerWhitelist(t *testing.T) {
142143
runTest(&g)
143144
})
144145
}
146+
147+
func TestWakeBlockReward(t *testing.T) {
148+
r := require.New(t)
149+
four, five := unit.ConvertIotxToRau(4), unit.ConvertIotxToRau(5)
150+
four.Add(four, five)
151+
four.Rsh(four, 1)
152+
wake := Default.WakeBlockReward()
153+
// wake block reward = 4.8, between 4.5 and 5
154+
r.Equal(1, wake.Cmp(four))
155+
r.Equal(-1, wake.Cmp(five))
156+
}

db/batch/batch.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ type (
4040
ClearAndUnlock()
4141
// Put insert or update a record identified by (namespace, key)
4242
Put(string, []byte, []byte, string)
43+
// Append appends a KVStoreBatch to the current batch
44+
Append(KVStoreBatch)
4345
// Delete deletes a record by (namespace, key)
4446
Delete(string, []byte, string)
4547
// Size returns the size of batch

db/batch/batch_impl.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,27 @@ func (b *baseKVStoreBatch) Put(namespace string, key, value []byte, errorMessage
7777
b.batch(Put, namespace, key, value, errorMessage)
7878
}
7979

80+
func (b *baseKVStoreBatch) Append(kvb KVStoreBatch) {
81+
b.mutex.Lock()
82+
defer b.mutex.Unlock()
83+
kvb.Lock()
84+
defer kvb.Unlock()
85+
for i := 0; i < kvb.Size(); i++ {
86+
wi, err := b.Entry(i)
87+
if err != nil {
88+
panic(err)
89+
}
90+
switch wi.writeType {
91+
case Put:
92+
b.batch(Put, wi.namespace, wi.key, wi.value, wi.errorMessage)
93+
case Delete:
94+
b.batch(Delete, wi.namespace, wi.key, nil, wi.errorMessage)
95+
default:
96+
panic("unexpected write type")
97+
}
98+
}
99+
}
100+
80101
// Delete deletes a record
81102
func (b *baseKVStoreBatch) Delete(namespace string, key []byte, errorMessage string) {
82103
b.mutex.Lock()
@@ -280,16 +301,45 @@ func (cb *cachedBatch) touchKey(h kvCacheKey) {
280301
func (cb *cachedBatch) Put(namespace string, key, value []byte, errorMessage string) {
281302
cb.lock.Lock()
282303
defer cb.lock.Unlock()
304+
cb.put(namespace, key, value, errorMessage)
305+
}
306+
307+
func (cb *cachedBatch) put(namespace string, key, value []byte, errorMessage string) {
283308
h := cb.hash(namespace, key)
284309
cb.touchKey(h)
285310
cb.currentCache().Write(&h, value)
286311
cb.kvStoreBatch.batch(Put, namespace, key, value, errorMessage)
287312
}
288313

314+
func (cb *cachedBatch) Append(b KVStoreBatch) {
315+
cb.lock.Lock()
316+
defer cb.lock.Unlock()
317+
b.Lock()
318+
defer b.Unlock()
319+
for i := 0; i < b.Size(); i++ {
320+
wi, err := b.Entry(i)
321+
if err != nil {
322+
panic(err)
323+
}
324+
switch wi.writeType {
325+
case Put:
326+
cb.put(wi.namespace, wi.key, wi.value, wi.errorMessage)
327+
case Delete:
328+
cb.delete(wi.namespace, wi.key, wi.errorMessage)
329+
default:
330+
panic("unexpected write type")
331+
}
332+
}
333+
}
334+
289335
// Delete deletes a record
290336
func (cb *cachedBatch) Delete(namespace string, key []byte, errorMessage string) {
291337
cb.lock.Lock()
292338
defer cb.lock.Unlock()
339+
cb.delete(namespace, key, errorMessage)
340+
}
341+
342+
func (cb *cachedBatch) delete(namespace string, key []byte, errorMessage string) {
293343
h := cb.hash(namespace, key)
294344
cb.touchKey(h)
295345
cb.currentCache().Evict(&h)

db/batch/batch_impl_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ func TestBaseKVStoreBatch(t *testing.T) {
7171
require.NoError(err)
7272
require.Equal("to_delete_ns", newEntry1.Namespace())
7373
require.Equal(Put, newEntry1.WriteType())
74+
bb := NewBatch()
75+
bb.Put("bb", []byte("bbkey"), []byte("bbvalue"), "")
76+
bb.Put("bb", []byte("bbkey2"), []byte("bbvalue2"), "")
77+
b.Append(bb)
78+
require.Equal(4, b.Size())
7479
b.Clear()
7580
require.Equal(0, b.Size())
7681
}
@@ -136,6 +141,11 @@ func TestCachedBatch(t *testing.T) {
136141
}
137142
return wi
138143
}).SerializeQueue(nil, nil)))
144+
bb := NewCachedBatch()
145+
bb.Put("bb", []byte("bbkey"), []byte("bbvalue"), "")
146+
bb.Put("bb", []byte("bbkey2"), []byte("bbvalue2"), "")
147+
cb.Append(bb)
148+
require.Equal(3, cb.Size())
139149
cb.Clear()
140150
require.Equal(0, cb.Size())
141151
}

db/kvstorewithbuffer.go

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"github.com/pkg/errors"
99

1010
"github.com/iotexproject/iotex-core/v2/db/batch"
11-
"github.com/iotexproject/iotex-core/v2/pkg/log"
1211
)
1312

1413
type (
@@ -248,38 +247,6 @@ func (kvb *kvStoreWithBuffer) Filter(ns string, cond Condition, minKey, maxKey [
248247
}
249248

250249
func (kvb *kvStoreWithBuffer) WriteBatch(b batch.KVStoreBatch) (err error) {
251-
b.Lock()
252-
defer func() {
253-
if err == nil {
254-
// clear the batch if commit succeeds
255-
b.ClearAndUnlock()
256-
} else {
257-
b.Unlock()
258-
}
259-
}()
260-
writes := make([]*batch.WriteInfo, b.Size())
261-
for i := 0; i < b.Size(); i++ {
262-
write, e := b.Entry(i)
263-
if e != nil {
264-
return e
265-
}
266-
if write.WriteType() != batch.Put && write.WriteType() != batch.Delete {
267-
return errors.Errorf("invalid write type %d", write.WriteType())
268-
}
269-
writes[i] = write
270-
}
271-
kvb.buffer.Lock()
272-
defer kvb.buffer.Unlock()
273-
for _, write := range writes {
274-
switch write.WriteType() {
275-
case batch.Put:
276-
kvb.buffer.Put(write.Namespace(), write.Key(), write.Value(), write.Error())
277-
case batch.Delete:
278-
kvb.buffer.Delete(write.Namespace(), write.Key(), write.Error())
279-
default:
280-
log.S().Panic("unexpected write type")
281-
}
282-
}
283-
250+
kvb.buffer.Append(b)
284251
return nil
285252
}

0 commit comments

Comments
 (0)