Skip to content
This repository was archived by the owner on Apr 4, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
7fdae38
first strokes
patrick-ogrady Jan 2, 2022
8653b7f
more scoping
patrick-ogrady Jan 2, 2022
e4e6b3e
add additional todo
patrick-ogrady Jan 4, 2022
2450c1a
cleanup underway
patrick-ogrady Jan 6, 2022
6e0a24c
more progress
patrick-ogrady Jan 6, 2022
eab928c
more progress
patrick-ogrady Jan 6, 2022
5679700
everything compiles
patrick-ogrady Jan 6, 2022
a788ec3
fix integration test
patrick-ogrady Jan 6, 2022
be531ae
cleanup
patrick-ogrady Jan 6, 2022
9a54fbe
fix hash issue
patrick-ogrady Jan 6, 2022
25006bf
automatically generate raw prefix in storage
patrick-ogrady Jan 6, 2022
4b78fa1
revert auto hash generation
patrick-ogrady Jan 6, 2022
84fc802
first pass on expiry keys
patrick-ogrady Jan 6, 2022
0e34537
jank pruning
patrick-ogrady Jan 6, 2022
efbb435
expiring tests
patrick-ogrady Jan 6, 2022
e98e50c
fix tests
patrick-ogrady Jan 6, 2022
aeb1821
add context locking
patrick-ogrady Jan 6, 2022
b8e57b4
add logging
patrick-ogrady Jan 6, 2022
14ee27e
cleanup db at end of test
patrick-ogrady Jan 6, 2022
085be1e
fix rprefix gen
patrick-ogrady Jan 6, 2022
ada6ee8
fix init issue
patrick-ogrady Jan 6, 2022
dd2169d
fix pruning correctness
patrick-ogrady Jan 6, 2022
81a81e7
fix difficulty estimate
patrick-ogrady Jan 6, 2022
1296705
working again
patrick-ogrady Jan 6, 2022
2dad05e
fix underflow
patrick-ogrady Jan 6, 2022
ad5a558
vm: missing "<-donecPrune"
gyuho Jan 6, 2022
ecfb929
chain: use "ids.ShortEmpty"
gyuho Jan 6, 2022
bf70964
chain: add "PutPrefixInfo/Key" tests
gyuho Jan 6, 2022
a16f187
chain: document new storage functions
gyuho Jan 6, 2022
d0cfc38
chain: fix error checks
gyuho Jan 6, 2022
f2e68b4
chain: define "extractSpecificTimeKey"
gyuho Jan 6, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ linters:
- exhaustive
- exportloopref
- forcetypeassert
- gocognit
- goconst
- gocritic
- gofmt
Expand Down Expand Up @@ -72,6 +71,7 @@ linters:
# - exhaustivestruct
# - forbidigo
# - funlen
# - gocognit
# - godot
# - goerr113
# - gomnd
Expand All @@ -84,8 +84,6 @@ linters:
# - wsl

linters-settings:
gocognit:
min-complexity: 37
gocritic:
disabled-checks:
- appendAssign
Expand Down
22 changes: 20 additions & 2 deletions chain/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,14 @@ func (b *StatelessBlock) verify() (*StatelessBlock, *versiondb.Database, error)
return nil, nil, err
}
onAcceptDB := versiondb.New(parentState)

// Remove all expired prefixes
if err := ExpireNext(onAcceptDB, parent.Tmstmp, b.Tmstmp); err != nil {
return nil, nil, err
}

// Process new transactions
log.Debug("build context", "next difficulty", context.NextDifficulty, "next cost", context.NextCost)
var surplusDifficulty uint64
for _, tx := range b.Txs {
if err := tx.Execute(onAcceptDB, b.Tmstmp, context); err != nil {
Expand All @@ -159,7 +167,9 @@ func (b *StatelessBlock) verify() (*StatelessBlock, *versiondb.Database, error)
surplusDifficulty += tx.Difficulty() - context.NextDifficulty
}
// Ensure enough work is performed to compensate for block production speed
if surplusDifficulty < b.Difficulty*b.Cost {
requiredSurplus := b.Difficulty * b.Cost
if surplusDifficulty < requiredSurplus {
log.Debug("insufficient block surplus", "found", surplusDifficulty, "required", requiredSurplus)
return nil, nil, ErrInsufficientSurplus
}
return parent, onAcceptDB, nil
Expand Down Expand Up @@ -195,7 +205,6 @@ func (b *StatelessBlock) Accept() error {
}
b.st = choices.Accepted
b.vm.Accepted(b)
// TODO: clear expired state (using index from timestamp to prefix)
return nil
}

Expand All @@ -221,6 +230,15 @@ func (b *StatelessBlock) Height() uint64 { return b.StatefulBlock.Hght }
// implements "snowman.Block"
func (b *StatelessBlock) Timestamp() time.Time { return b.t }

func (b *StatelessBlock) SetChildrenDB(db database.Database) error {
for _, child := range b.children {
if err := child.onAcceptDB.SetDatabase(db); err != nil {
return err
}
}
return nil
}

func (b *StatelessBlock) onAccept() (database.Database, error) {
if b.st == choices.Accepted || b.Hght == 0 /* genesis */ {
return b.vm.State(), nil
Expand Down
19 changes: 7 additions & 12 deletions chain/claim_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,30 +24,25 @@ func (c *ClaimTx) Execute(db database.Database, blockTime int64) error {
return ErrPublicKeyMismatch
}

prevInfo, infoExists, err := GetPrefixInfo(db, c.Prefix)
// Prefix keys only exist if they are still valid
exists, err := HasPrefix(db, c.Prefix)
if err != nil {
return err
}
if infoExists && prevInfo.Expiry >= blockTime {
if exists {
return ErrPrefixNotExpired
}

// every successful "claim" deletes the existing keys
// whether "c.Sender" is same as or different than "prevInfo.Owner"
// now write with either prefix expired or new prefix owner
// Anything previously at the prefix was previously removed...
newInfo := &PrefixInfo{
Owner: c.Sender,
Created: blockTime,
LastUpdated: blockTime,
Expiry: blockTime + expiryTime,
Keys: 1,
}
if err := PutPrefixInfo(db, c.Prefix, newInfo); err != nil {
if err := PutPrefixInfo(db, c.Prefix, newInfo, -1); err != nil {
return err
}

// Remove anything that is stored in value prefix
// overwrite even if claimed by the same owner
// TODO(patrick-ogrady): free things async for faster block verification loops
// e.g., lazily free what is said to be freed in the block?
return DeleteAllPrefixKeys(db, c.Prefix)
return nil
}
21 changes: 21 additions & 0 deletions chain/claim_tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ func TestClaimTx(t *testing.T) {
},
}
for i, tv := range tt {
if i > 0 {
// Expire old prefixes between txs
if err := ExpireNext(db, tt[i-1].blockTime, tv.blockTime); err != nil {
t.Fatalf("#%d: ExpireNext errored %v", i, err)
}
}
err := tv.tx.Execute(db, tv.blockTime)
if !errors.Is(err, tv.err) {
t.Fatalf("#%d: tx.Execute err expected %v, got %v", i, tv.err, err)
Expand All @@ -85,4 +91,19 @@ func TestClaimTx(t *testing.T) {
t.Fatalf("#%d: unexpected owner found (expected pub key %q)", i, string(pub.PublicKey))
}
}

// Cleanup DB after all txs submitted
if err := ExpireNext(db, 0, 1000); err != nil {
t.Fatal(err)
}
if err := PruneNext(db, 100); err != nil {
t.Fatal(err)
}
_, exists, err := GetPrefixInfo(db, []byte("foo"))
if err != nil {
t.Fatalf("failed to get prefix info %v", err)
}
if exists {
t.Fatal("prefix should not exist")
}
}
3 changes: 2 additions & 1 deletion chain/lifeline_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ func (l *LifelineTx) Execute(db database.Database, blockTime int64) error {
return ErrPrefixMissing
}
// If you are "in debt", lifeline only adds but doesn't reset to new
lastExpiry := i.Expiry
i.Expiry += expiryTime / i.Keys
return PutPrefixInfo(db, l.Prefix, i)
return PutPrefixInfo(db, l.Prefix, i, lastExpiry)
}
2 changes: 1 addition & 1 deletion chain/lifeline_tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func TestLifelineTx(t *testing.T) {
blockTime: 1,
err: nil,
},
{ // successful lifeline when prefix info is missing
{ // successful lifeline when prefix info is not missing
utx: &LifelineTx{BaseTx: &BaseTx{Sender: pub.Bytes(), Prefix: []byte("foo")}},
blockTime: 1,
err: nil,
Expand Down
4 changes: 4 additions & 0 deletions chain/prefix_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@
package chain

import (
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/quarkvm/crypto"
)

type PrefixInfo struct {
Owner [crypto.PublicKeySize]byte `serialize:"true" json:"owner"`
Created int64 `serialize:"true" json:"created"`
LastUpdated int64 `serialize:"true" json:"lastUpdated"`
Expiry int64 `serialize:"true" json:"expiry"`
Keys int64 `serialize:"true" json:"keys"` // decays faster the more keys you have

RawPrefix ids.ShortID `serialize:"true" json:"rawPrefix"`
}
5 changes: 3 additions & 2 deletions chain/set_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func (s *SetTx) Execute(db database.Database, blockTime int64) error {
return s.updatePrefix(db, blockTime, i)
}

func (s *SetTx) updatePrefix(db database.KeyValueWriter, blockTime int64, i *PrefixInfo) error {
func (s *SetTx) updatePrefix(db database.Database, blockTime int64, i *PrefixInfo) error {
timeRemaining := (i.Expiry - i.LastUpdated) * i.Keys
if len(s.Value) == 0 {
i.Keys--
Expand All @@ -80,6 +80,7 @@ func (s *SetTx) updatePrefix(db database.KeyValueWriter, blockTime int64, i *Pre
}
newTimeRemaining := timeRemaining / i.Keys
i.LastUpdated = blockTime
lastExpiry := i.Expiry
i.Expiry = blockTime + newTimeRemaining
return PutPrefixInfo(db, s.Prefix, i)
return PutPrefixInfo(db, s.Prefix, i, lastExpiry)
}
6 changes: 5 additions & 1 deletion chain/set_tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,11 @@ func TestSetTx(t *testing.T) {
t.Fatalf("#%d: unexpected owner found (expected pub key %q)", i, string(pub.PublicKey))
}
// each claim must delete all existing keys with the value key
if kvs := Range(db, tp.Prefix, nil, WithPrefix()); len(kvs) > 0 {
kvs, err := Range(db, tp.Prefix, nil, WithPrefix())
if err != nil {
t.Fatalf("#%d: unexpected error when fetching range %v", i, err)
}
if len(kvs) > 0 {
t.Fatalf("#%d: unexpected key-values for the prefix after claim", i)
}

Expand Down
Loading