Skip to content
This repository was archived by the owner on Apr 4, 2023. It is now read-only.

Commit 54102b4

Browse files
Merge pull request #77 from ava-labs/cleanup-genesis
Final Launch Tweaks
2 parents 4d9f29c + 8790bee commit 54102b4

22 files changed

+210
-187
lines changed

chain/block.go

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -139,21 +139,31 @@ func (b *StatelessBlock) ID() ids.ID { return b.id }
139139
func (b *StatelessBlock) verify() (*StatelessBlock, *versiondb.Database, error) {
140140
g := b.vm.Genesis()
141141

142+
// Perform basic correctness checks before doing any expensive work
143+
if len(b.Txs) == 0 {
144+
return nil, nil, ErrNoTxs
145+
}
146+
if b.Timestamp().Unix() >= time.Now().Add(futureBound).Unix() {
147+
return nil, nil, ErrTimestampTooLate
148+
}
149+
blockSize := uint64(0)
150+
for _, tx := range b.Txs {
151+
blockSize += tx.LoadUnits(g)
152+
if blockSize > g.MaxBlockSize {
153+
return nil, nil, ErrBlockTooBig
154+
}
155+
}
156+
157+
// Verify parent is available
142158
parent, err := b.vm.GetStatelessBlock(b.Prnt)
143159
if err != nil {
144160
log.Debug("could not get parent", "id", b.Prnt)
145161
return nil, nil, err
146162
}
147-
148-
if len(b.Txs) == 0 {
149-
return nil, nil, ErrNoTxs
150-
}
151163
if b.Timestamp().Unix() < parent.Timestamp().Unix() {
152164
return nil, nil, ErrTimestampTooEarly
153165
}
154-
if b.Timestamp().Unix() >= time.Now().Add(futureBound).Unix() {
155-
return nil, nil, ErrTimestampTooLate
156-
}
166+
157167
context, err := b.vm.ExecutionContext(b.Tmstmp, parent)
158168
if err != nil {
159169
return nil, nil, err

chain/block_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,11 +171,10 @@ func createTestBlk(
171171
vm := NewMockVM(ctrl)
172172
vm.EXPECT().Genesis().Return(DefaultGenesis()).AnyTimes()
173173
parentBlk.vm = vm
174-
175174
if err := parentBlk.init(); err != nil {
176175
t.Fatal(err)
177176
}
178-
vm.EXPECT().GetStatelessBlock(parentBlk.ID()).Return(parentBlk, nil)
177+
vm.EXPECT().GetStatelessBlock(parentBlk.ID()).Return(parentBlk, nil).AnyTimes()
179178

180179
blk := NewBlock(vm, parentBlk, blkTmpstp, blkCtx)
181180
if uint64(blk.StatefulBlock.Tmstmp) != uint64(blkTmpstp) {

chain/builder.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,28 @@ func BuildBlock(vm VM, preferred ids.ID) (snowman.Block, error) {
4848
b.Winners = map[ids.ID]*Activity{}
4949
b.Txs = []*Transaction{}
5050
units := uint64(0)
51-
for units < g.TargetUnits && mempool.Len() > 0 {
51+
52+
// Restorable txs after block attempt finishes
53+
unusableTxs := []*Transaction{}
54+
defer func() {
55+
for _, tx := range unusableTxs {
56+
mempool.Add(tx)
57+
}
58+
}()
59+
60+
for mempool.Len() > 0 {
5261
next, price := mempool.PopMax()
5362
if price < b.Price {
5463
mempool.Add(next)
55-
log.Debug("skipping tx: too low price", "block price", b.Price, "tx price", next.GetPrice())
64+
log.Debug("skipping tx: too low price", "block price", b.Price, "tx price", price)
5665
break
5766
}
67+
nextLoad := next.LoadUnits(g)
68+
if units+nextLoad > g.MaxBlockSize {
69+
unusableTxs = append(unusableTxs, next)
70+
log.Debug("skipping tx: too large", "block size", units, "tx load", nextLoad)
71+
continue // could be txs that fit that are smaller
72+
}
5873
// Verify that changes pass
5974
tvdb := versiondb.New(vdb)
6075
if err := next.Execute(g, tvdb, b, context); err != nil {
@@ -66,7 +81,7 @@ func BuildBlock(vm VM, preferred ids.ID) (snowman.Block, error) {
6681
}
6782
// Wait to add prefix until after verification
6883
b.Txs = append(b.Txs, next)
69-
units += next.LoadUnits(g)
84+
units += nextLoad
7085
}
7186
vdb.Abort()
7287

chain/claim_tx.go

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -63,29 +63,27 @@ func (c *ClaimTx) Execute(t *TransactionContext) error {
6363
return nil
6464
}
6565

66-
// [spaceUnits] requires the caller to pay more to get spaces of
66+
// [spaceNameUnits] requires the caller to pay more to get spaces of
6767
// a shorter length because they are more desirable. This creates a "lottery"
6868
// mechanism where the people that spend the most mining power will win the
6969
// space.
7070
//
71-
// [spaceUnits] should only be called on a space that is valid
72-
func spaceUnits(g *Genesis, s string) uint64 {
71+
// [spaceNameUnits] should only be called on a space that is valid
72+
func spaceNameUnits(g *Genesis, s string) uint64 {
7373
desirability := uint64(parser.MaxIdentifierSize - len(s))
74-
if uint64(len(s)) > g.ClaimTier2Size {
75-
return desirability * g.ClaimTier3Multiplier
74+
desirability *= g.SpaceDesirabilityMultiplier
75+
if desirability < g.MinClaimFee {
76+
return g.MinClaimFee
7677
}
77-
if uint64(len(s)) > g.ClaimTier1Size {
78-
return desirability * g.ClaimTier2Multiplier
79-
}
80-
return desirability * g.ClaimTier1Multiplier
78+
return desirability
8179
}
8280

8381
func (c *ClaimTx) FeeUnits(g *Genesis) uint64 {
84-
return c.LoadUnits(g) + spaceUnits(g, c.Space)
82+
return c.LoadUnits(g) + spaceNameUnits(g, c.Space)
8583
}
8684

8785
func (c *ClaimTx) LoadUnits(g *Genesis) uint64 {
88-
return c.BaseTx.LoadUnits(g) * g.ClaimFeeMultiplier
86+
return c.BaseTx.LoadUnits(g) * g.ClaimLoadMultiplier
8987
}
9088

9189
func (c *ClaimTx) Copy() UnsignedTransaction {

chain/codec.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ const (
1414
// codecVersion is the current default codec version
1515
codecVersion = 0
1616

17-
// maxSize is 2MB to support large values
18-
maxSize = 2 * units.MiB
17+
// maxSize is 4MB to support large values
18+
maxSize = 4 * units.MiB
1919
)
2020

2121
var codecManager codec.Manager

chain/errors.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import (
88
)
99

1010
var (
11+
// Genesis Correctness
12+
ErrInvalidMagic = errors.New("invalid magic")
13+
ErrInvalidBlockRate = errors.New("invalid block rate")
14+
1115
// Block Correctness
1216
ErrTimestampTooEarly = errors.New("block timestamp too early")
1317
ErrTimestampTooLate = errors.New("block timestamp too late")
@@ -18,7 +22,6 @@ var (
1822
ErrParentBlockNotVerified = errors.New("parent block not verified or accepted")
1923

2024
// Tx Correctness
21-
ErrInvalidMagic = errors.New("invalid magic")
2225
ErrInvalidBlockID = errors.New("invalid blockID")
2326
ErrInvalidSignature = errors.New("invalid signature")
2427
ErrDuplicateTx = errors.New("duplicate transaction")
@@ -38,4 +41,5 @@ var (
3841
ErrUnauthorized = errors.New("sender is not authorized")
3942
ErrInvalidBalance = errors.New("invalid balance")
4043
ErrNonActionable = errors.New("transaction doesn't do anything")
44+
ErrBlockTooBig = errors.New("block too big")
4145
)

chain/genesis.go

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@ import (
1616
log "github.com/inconshreveable/log15"
1717
)
1818

19+
const (
20+
LotteryRewardDivisor = 100
21+
MinBlockCost = 0
22+
23+
DefaultFreeClaimStorage = 1 * units.MiB
24+
DefaultValueUnitSize = 1 * units.KiB
25+
DefaultFreeClaimUnits = DefaultFreeClaimStorage / DefaultValueUnitSize
26+
DefaultFreeClaimDuration = 60 * 60 * 24 * 30 // 30 Days
27+
28+
DefaultLookbackWindow = 60
29+
)
30+
1931
type Airdrop struct {
2032
// Address strings are hex-formatted common.Address
2133
Address common.Address `serialize:"true" json:"address"`
@@ -38,30 +50,26 @@ type Genesis struct {
3850
MaxValueSize uint64 `serialize:"true" json:"maxValueSize"`
3951

4052
// Claim Params
41-
ClaimFeeMultiplier uint64 `serialize:"true" json:"claimFeeMultiplier"`
42-
ClaimTier3Multiplier uint64 `serialize:"true" json:"claimTier3Multiplier"`
43-
ClaimTier2Size uint64 `serialize:"true" json:"claimTier2Size"`
44-
ClaimTier2Multiplier uint64 `serialize:"true" json:"claimTier2Multiplier"`
45-
ClaimTier1Size uint64 `serialize:"true" json:"claimTier1Size"`
46-
ClaimTier1Multiplier uint64 `serialize:"true" json:"claimTier1Multiplier"`
53+
ClaimLoadMultiplier uint64 `serialize:"true" json:"claimLoadMultiplier"`
54+
MinClaimFee uint64 `serialize:"true" json:"minClaimFee"`
55+
SpaceDesirabilityMultiplier uint64 `serialize:"true" json:"spaceDesirabilityMultiplier"`
4756

4857
// Lifeline Params
49-
PrefixRenewalDiscount uint64 `serialize:"true" json:"prefixRenewalDiscount"`
58+
SpaceRenewalDiscount uint64 `serialize:"true" json:"prefixRenewalDiscount"`
5059

5160
// Reward Params
52-
ClaimReward uint64 `serialize:"true" json:"claimReward"`
53-
LifelineUnitReward uint64 `serialize:"true" json:"lifelineUnitReward"`
61+
ClaimReward uint64 `serialize:"true" json:"claimReward"`
5462

5563
// Mining Reward (% of min required fee)
56-
LotteryRewardMultipler uint64 `serialize:"true" json:"lotteryRewardMultipler"`
57-
LotteryRewardDivisor uint64 `serialize:"true" json:"lotteryRewardDivisor"`
64+
LotteryRewardMultipler uint64 `serialize:"true" json:"lotteryRewardMultipler"` // divided by 100
5865

5966
// Fee Mechanism Params
60-
LookbackWindow int64 `serialize:"true" json:"lookbackWindow"`
61-
BlockTarget int64 `serialize:"true" json:"blockTarget"`
62-
TargetUnits uint64 `serialize:"true" json:"targetUnits"`
63-
MinPrice uint64 `serialize:"true" json:"minPrice"`
64-
MinBlockCost uint64 `serialize:"true" json:"minBlockCost"`
67+
MinPrice uint64 `serialize:"true" json:"minPrice"`
68+
LookbackWindow int64 `serialize:"true" json:"lookbackWindow"`
69+
TargetBlockRate int64 `serialize:"true" json:"targetBlockRate"` // seconds
70+
TargetBlockSize uint64 `serialize:"true" json:"targetBlockSize"` // units
71+
MaxBlockSize uint64 `serialize:"true" json:"maxBlockSize"` // units
72+
BlockCostEnabled bool `serialize:"true" json:"blockCostEnabled"`
6573

6674
// Allocations
6775
CustomAllocation []*CustomAllocation `serialize:"true" json:"customAllocation"`
@@ -72,51 +80,50 @@ type Genesis struct {
7280
func DefaultGenesis() *Genesis {
7381
return &Genesis{
7482
// Tx params
75-
BaseTxUnits: 10,
83+
BaseTxUnits: 1,
7684

7785
// SetTx params
78-
ValueUnitSize: 256, // 256B
79-
MaxValueSize: 64 * units.KiB, // (250 Units)
86+
ValueUnitSize: DefaultValueUnitSize,
87+
MaxValueSize: 256 * units.KiB,
8088

8189
// Claim Params
82-
ClaimFeeMultiplier: 5,
83-
ClaimTier3Multiplier: 1,
84-
ClaimTier2Size: 36,
85-
ClaimTier2Multiplier: 5,
86-
ClaimTier1Size: 12,
87-
ClaimTier1Multiplier: 25,
90+
ClaimLoadMultiplier: 5,
91+
MinClaimFee: 100,
92+
SpaceDesirabilityMultiplier: 5,
8893

8994
// Lifeline Params
90-
PrefixRenewalDiscount: 5,
95+
SpaceRenewalDiscount: 10,
9196

9297
// Reward Params
93-
ClaimReward: 60 * 60 * 24 * 15, // 15 Days
94-
LifelineUnitReward: 60 * 60, // 1 Hours Per Fee Unit
98+
ClaimReward: DefaultFreeClaimUnits * DefaultFreeClaimDuration,
9599

96-
// Lottery Reward (80% of tx.FeeUnits() * block.Price)
97-
LotteryRewardMultipler: 8,
98-
LotteryRewardDivisor: 10,
100+
// Lottery Reward (50% of tx.FeeUnits() * block.Price)
101+
LotteryRewardMultipler: 50,
99102

100103
// Fee Mechanism Params
101-
LookbackWindow: 60, // 60 Seconds
102-
BlockTarget: 1, // 1 Block per Second
103-
TargetUnits: 10 * 512 * 60, // 5012 Units Per Block (~1.2MB of SetTx)
104-
MinPrice: 1, // (50 for easiest claim)
105-
MinBlockCost: 0, // Minimum Unit Overhead
104+
LookbackWindow: DefaultLookbackWindow, // 60 Seconds
105+
TargetBlockRate: 1, // 1 Block per Second
106+
TargetBlockSize: 1500, // 1500 Units Per Block (~1.5MB of SetTx)
107+
MaxBlockSize: 2000, // 2000 Units (~2MB)
108+
MinPrice: 1,
109+
BlockCostEnabled: true,
106110
}
107111
}
108112

109113
func (g *Genesis) StatefulBlock() *StatefulBlock {
110114
return &StatefulBlock{
111115
Price: g.MinPrice,
112-
Cost: g.MinBlockCost,
116+
Cost: MinBlockCost,
113117
}
114118
}
115119

116120
func (g *Genesis) Verify() error {
117121
if g.Magic == 0 {
118122
return ErrInvalidMagic
119123
}
124+
if g.TargetBlockRate == 0 {
125+
return ErrInvalidBlockRate
126+
}
120127
return nil
121128
}
122129

chain/lifeline_tx.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ type LifelineTx struct {
2828
}
2929

3030
func (l *LifelineTx) Execute(t *TransactionContext) error {
31+
if l.Units == 0 {
32+
return ErrNonActionable
33+
}
34+
3135
if err := parser.CheckContents(l.Space); err != nil {
3236
return err
3337
}
@@ -43,20 +47,24 @@ func (l *LifelineTx) Execute(t *TransactionContext) error {
4347
}
4448
// Lifeline spread across all units
4549
lastExpiry := i.Expiry
46-
i.Expiry += g.LifelineUnitReward * l.Units / i.Units
50+
i.Expiry += (g.ClaimReward * l.Units) / i.Units
4751
return PutSpaceInfo(t.Database, []byte(l.Space), i, lastExpiry)
4852
}
4953

5054
func (l *LifelineTx) FeeUnits(g *Genesis) uint64 {
5155
// FeeUnits are discounted so that, all else equal, it is easier for an owner
5256
// to retain their space than for another to claim it.
53-
discountedPrefixUnits := spaceUnits(g, l.Space) / g.PrefixRenewalDiscount
57+
dSpaceNameUnits := spaceNameUnits(g, l.Space) / g.SpaceRenewalDiscount
5458

5559
// The more desirable the space, the more it costs to maintain it.
5660
//
5761
// Note, this heavy base cost incentivizes users to send fewer transactions
5862
// to extend their space's life instead of many small ones.
59-
return l.LoadUnits(g) + discountedPrefixUnits + l.Units
63+
return l.LoadUnits(g) + dSpaceNameUnits*l.Units
64+
}
65+
66+
func (l *LifelineTx) LoadUnits(g *Genesis) uint64 {
67+
return l.BaseTx.LoadUnits(g) * g.ClaimLoadMultiplier
6068
}
6169

6270
func (l *LifelineTx) Copy() UnsignedTransaction {

chain/lifeline_tx_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func TestLifelineTx(t *testing.T) {
3333
err error
3434
}{
3535
{ // invalid when prefix info is missing
36-
utx: &LifelineTx{BaseTx: &BaseTx{}, Space: "foo"},
36+
utx: &LifelineTx{BaseTx: &BaseTx{}, Space: "foo", Units: 1},
3737
blockTime: 1,
3838
sender: sender,
3939
err: ErrSpaceMissing,
@@ -44,10 +44,16 @@ func TestLifelineTx(t *testing.T) {
4444
sender: sender,
4545
err: nil,
4646
},
47-
{ // successful lifeline when prefix info is not missing
47+
{ // invalid when units is missing
4848
utx: &LifelineTx{BaseTx: &BaseTx{}, Space: "foo"},
4949
blockTime: 1,
5050
sender: sender,
51+
err: ErrNonActionable,
52+
},
53+
{ // successful lifeline when prefix info and units is not missing
54+
utx: &LifelineTx{BaseTx: &BaseTx{}, Space: "foo", Units: 1},
55+
blockTime: 1,
56+
sender: sender,
5157
err: nil,
5258
},
5359
{ // successful lifeline non-zero units

chain/mempool_mock.go

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)