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

Commit 0c2acd2

Browse files
Merge pull request #54 from ava-labs/remove-pow
Remove POW [Part 1]
2 parents f8efffc + 44df9cc commit 0c2acd2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1351
-930
lines changed

chain/base_tx.go

Lines changed: 46 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,57 +4,69 @@
44
package chain
55

66
import (
7-
"bytes"
8-
97
"github.com/ava-labs/avalanchego/ids"
10-
"github.com/ava-labs/avalanchego/utils/crypto"
11-
12-
"github.com/ava-labs/quarkvm/parser"
138
)
149

15-
var emptyPublicKeyBytes [crypto.SECP256K1RPKLen]byte
16-
1710
type BaseTx struct {
18-
Sender [crypto.SECP256K1RPKLen]byte `serialize:"true" json:"sender"`
19-
Graffiti uint64 `serialize:"true" json:"graffiti"`
20-
BlockID ids.ID `serialize:"true" json:"blockId"`
11+
// BlkID is the ID of a block in the [lookbackWindow].
12+
BlkID ids.ID `serialize:"true" json:"blockId"`
2113

2214
// Prefix is the namespace for the "PrefixInfo"
2315
// whose owner can write and read value for the
2416
// specific key space.
2517
// The prefix must not have the delimiter '/' as suffix.
2618
// Otherwise, the verification will fail.
27-
Prefix []byte `serialize:"true" json:"prefix"`
19+
20+
// TODO: change to string
21+
// TODO: move to each tx
22+
Pfx []byte `serialize:"true" json:"prefix"`
23+
24+
// Magic is a value defined in genesis to protect against replay attacks on
25+
// different VMs.
26+
Mgc uint64 `serialize:"true" json:"magic"`
27+
28+
// Price is the value per unit to spend on this transaction.
29+
Prce uint64 `serialize:"true" json:"fee"`
2830
}
2931

30-
func (b *BaseTx) SetBlockID(blockID ids.ID) {
31-
b.BlockID = blockID
32+
func (b *BaseTx) BlockID() ids.ID {
33+
return b.BlkID
3234
}
3335

34-
func (b *BaseTx) SetGraffiti(graffiti uint64) {
35-
b.Graffiti = graffiti
36+
func (b *BaseTx) SetBlockID(bid ids.ID) {
37+
b.BlkID = bid
3638
}
3739

38-
func (b *BaseTx) GetBlockID() ids.ID {
39-
return b.BlockID
40+
func (b *BaseTx) Prefix() []byte {
41+
return b.Pfx
4042
}
4143

42-
func (b *BaseTx) GetSender() [crypto.SECP256K1RPKLen]byte {
43-
return b.Sender
44+
func (b *BaseTx) Magic() uint64 {
45+
return b.Mgc
4446
}
4547

46-
func (b *BaseTx) ExecuteBase() error {
47-
if err := parser.CheckPrefix(b.Prefix); err != nil {
48-
return err
49-
}
48+
func (b *BaseTx) SetMagic(magic uint64) {
49+
b.Mgc = magic
50+
}
5051

51-
if bytes.Equal(b.Sender[:], emptyPublicKeyBytes[:]) {
52-
return ErrInvalidSender
53-
}
52+
func (b *BaseTx) Price() uint64 {
53+
return b.Prce
54+
}
5455

55-
if b.BlockID == ids.Empty {
56+
func (b *BaseTx) SetPrice(price uint64) {
57+
b.Prce = price
58+
}
59+
60+
func (b *BaseTx) ExecuteBase(g *Genesis) error {
61+
if b.BlkID == ids.Empty {
5662
return ErrInvalidBlockID
5763
}
64+
if g.Magic != b.Mgc {
65+
return ErrInvalidMagic
66+
}
67+
if b.Prce < g.MinPrice {
68+
return ErrInvalidPrice
69+
}
5870
return nil
5971
}
6072

@@ -67,16 +79,14 @@ func (b *BaseTx) LoadUnits(g *Genesis) uint64 {
6779
}
6880

6981
func (b *BaseTx) Copy() *BaseTx {
70-
sender := [crypto.SECP256K1RPKLen]byte{}
71-
copy(sender[:], b.Sender[:])
7282
blockID := ids.ID{}
73-
copy(blockID[:], b.BlockID[:])
74-
prefix := make([]byte, len(b.Prefix))
75-
copy(prefix, b.Prefix)
83+
copy(blockID[:], b.BlkID[:])
84+
prefix := make([]byte, len(b.Pfx))
85+
copy(prefix, b.Pfx)
7686
return &BaseTx{
77-
Sender: sender,
78-
BlockID: blockID,
79-
Graffiti: b.Graffiti,
80-
Prefix: prefix,
87+
BlkID: blockID,
88+
Pfx: prefix,
89+
Mgc: b.Mgc,
90+
Prce: b.Prce,
8191
}
8292
}

chain/base_tx_test.go

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,60 +16,58 @@ import (
1616
func TestBaseTx(t *testing.T) {
1717
t.Parallel()
1818

19-
priv, err := f.NewPrivateKey()
20-
if err != nil {
21-
t.Fatal(err)
22-
}
23-
sender, err := FormatPK(priv.PublicKey())
24-
if err != nil {
25-
t.Fatal(err)
26-
}
27-
2819
tt := []struct {
29-
tx *BaseTx
30-
err error
20+
tx *BaseTx
21+
baseTxErr error
22+
prefixErr error
3123
}{
3224
{
33-
tx: &BaseTx{Sender: sender, Prefix: []byte("foo"), BlockID: ids.GenerateTestID()},
34-
err: nil,
25+
tx: &BaseTx{Pfx: []byte("foo"), BlkID: ids.GenerateTestID(), Prce: 1},
3526
},
3627
{
37-
tx: &BaseTx{Prefix: []byte("foo"), BlockID: ids.GenerateTestID()},
38-
err: ErrInvalidSender,
28+
tx: &BaseTx{Pfx: []byte("foo"), BlkID: ids.GenerateTestID()},
29+
baseTxErr: ErrInvalidPrice,
3930
},
4031
{
41-
tx: &BaseTx{Sender: sender, Prefix: []byte("fo/a")},
42-
err: parser.ErrInvalidDelimiter,
32+
tx: &BaseTx{Pfx: []byte("fo/a"), BlkID: ids.GenerateTestID()},
33+
prefixErr: parser.ErrInvalidDelimiter,
4334
},
4435
{
45-
tx: &BaseTx{Sender: sender, Prefix: []byte("foo/")},
46-
err: parser.ErrInvalidDelimiter,
36+
tx: &BaseTx{Pfx: []byte("foo/"), BlkID: ids.GenerateTestID()},
37+
prefixErr: parser.ErrInvalidDelimiter,
4738
},
4839
{
49-
tx: &BaseTx{Sender: sender, Prefix: []byte("foo")},
50-
err: ErrInvalidBlockID,
40+
tx: &BaseTx{Pfx: []byte("foo")},
41+
baseTxErr: ErrInvalidBlockID,
5142
},
5243
{
5344
tx: &BaseTx{
54-
Sender: sender,
55-
BlockID: ids.GenerateTestID(),
56-
Prefix: nil,
45+
BlkID: ids.GenerateTestID(),
46+
Pfx: nil,
5747
},
58-
err: parser.ErrPrefixEmpty,
48+
prefixErr: parser.ErrPrefixEmpty,
5949
},
6050
{
6151
tx: &BaseTx{
62-
Sender: sender,
63-
BlockID: ids.GenerateTestID(),
64-
Prefix: bytes.Repeat([]byte{'a'}, parser.MaxPrefixSize+1),
52+
BlkID: ids.GenerateTestID(),
53+
Pfx: bytes.Repeat([]byte{'a'}, parser.MaxPrefixSize+1),
6554
},
66-
err: parser.ErrPrefixTooBig,
55+
prefixErr: parser.ErrPrefixTooBig,
6756
},
6857
}
58+
g := DefaultGenesis()
6959
for i, tv := range tt {
70-
err := tv.tx.ExecuteBase()
71-
if !errors.Is(err, tv.err) {
72-
t.Fatalf("#%d: tx.Execute err expected %v, got %v", i, tv.err, err)
60+
err := tv.tx.ExecuteBase(g)
61+
if tv.baseTxErr != nil && !errors.Is(err, tv.baseTxErr) {
62+
t.Fatalf("#%d: tx.Execute err expected %v, got %v", i, tv.baseTxErr, err)
63+
}
64+
if tv.prefixErr == nil {
65+
continue
66+
}
67+
tx := &ClaimTx{BaseTx: tv.tx}
68+
err = tx.Execute(&TransactionContext{Genesis: g})
69+
if !errors.Is(err, tv.prefixErr) {
70+
t.Fatalf("#%d: tx.Execute err expected %v, got %v", i, tv.prefixErr, err)
7371
}
7472
}
7573
}

chain/block.go

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,21 @@ import (
1212
"github.com/ava-labs/avalanchego/ids"
1313
"github.com/ava-labs/avalanchego/snow/choices"
1414
"github.com/ava-labs/avalanchego/snow/consensus/snowman"
15+
"github.com/ava-labs/avalanchego/utils/hashing"
1516
log "github.com/inconshreveable/log15"
16-
"golang.org/x/crypto/sha3"
1717
)
1818

1919
const futureBound = 10 * time.Second
2020

2121
var _ snowman.Block = &StatelessBlock{}
2222

2323
type StatefulBlock struct {
24-
Prnt ids.ID `serialize:"true" json:"parent"`
25-
Tmstmp int64 `serialize:"true" json:"timestamp"`
26-
Hght uint64 `serialize:"true" json:"height"`
27-
Difficulty uint64 `serialize:"true" json:"difficulty"` // difficulty per unit
28-
Cost uint64 `serialize:"true" json:"cost"`
29-
Txs []*Transaction `serialize:"true" json:"txs"`
24+
Prnt ids.ID `serialize:"true" json:"parent"`
25+
Tmstmp int64 `serialize:"true" json:"timestamp"`
26+
Hght uint64 `serialize:"true" json:"height"`
27+
Price uint64 `serialize:"true" json:"price"`
28+
Cost uint64 `serialize:"true" json:"cost"`
29+
Txs []*Transaction `serialize:"true" json:"txs"`
3030

3131
Beneficiary []byte `serialize:"true" json:"beneficiary"` // prefix to reward
3232
}
@@ -53,7 +53,7 @@ func NewBlock(vm VM, parent snowman.Block, tmstp int64, beneficiary []byte, cont
5353
Tmstmp: tmstp,
5454
Prnt: parent.ID(),
5555
Hght: parent.Height() + 1,
56-
Difficulty: context.NextDifficulty,
56+
Price: context.NextPrice,
5757
Cost: context.NextCost,
5858
Beneficiary: beneficiary,
5959
},
@@ -94,8 +94,7 @@ func ParseStatefulBlock(
9494
st: status,
9595
vm: vm,
9696
}
97-
h := sha3.Sum256(b.bytes)
98-
id, err := ids.ToID(h[:])
97+
id, err := ids.ToID(hashing.ComputeHash256(b.bytes))
9998
if err != nil {
10099
return nil, err
101100
}
@@ -116,8 +115,7 @@ func (b *StatelessBlock) init() error {
116115
}
117116
b.bytes = bytes
118117

119-
h := sha3.Sum256(b.bytes)
120-
id, err := ids.ToID(h[:])
118+
id, err := ids.ToID(hashing.ComputeHash256(b.bytes))
121119
if err != nil {
122120
return err
123121
}
@@ -162,8 +160,8 @@ func (b *StatelessBlock) verify() (*StatelessBlock, *versiondb.Database, error)
162160
if b.Cost != context.NextCost {
163161
return nil, nil, ErrInvalidCost
164162
}
165-
if b.Difficulty != context.NextDifficulty {
166-
return nil, nil, ErrInvalidDifficulty
163+
if b.Price != context.NextPrice {
164+
return nil, nil, ErrInvalidPrice
167165
}
168166

169167
parentState, err := parent.onAccept()
@@ -182,19 +180,20 @@ func (b *StatelessBlock) verify() (*StatelessBlock, *versiondb.Database, error)
182180
}
183181

184182
// Process new transactions
185-
log.Debug("build context", "height", b.Hght, "difficulty", b.Difficulty, "cost", b.Cost)
186-
surplusWork := uint64(0)
183+
log.Debug("build context", "height", b.Hght, "price", b.Price, "cost", b.Cost)
184+
surplusFee := uint64(0)
187185
for _, tx := range b.Txs {
188186
if err := tx.Execute(g, onAcceptDB, b.Tmstmp, context); err != nil {
189187
return nil, nil, err
190188
}
191-
surplusWork += (tx.Difficulty() - b.Difficulty) * tx.FeeUnits(g)
189+
surplusFee += (tx.Price() - b.Price) * tx.FeeUnits(g)
192190
}
193-
// Ensure enough work is performed to compensate for block production speed
194-
requiredSurplus := b.Difficulty * b.Cost
195-
if surplusWork < requiredSurplus {
196-
return nil, nil, fmt.Errorf("%w: required=%d found=%d", ErrInsufficientSurplus, requiredSurplus, surplusWork)
191+
// Ensure enough fee is paid to compensate for block production speed
192+
requiredSurplus := b.Price * b.Cost
193+
if surplusFee < requiredSurplus {
194+
return nil, nil, fmt.Errorf("%w: required=%d found=%d", ErrInsufficientSurplus, requiredSurplus, surplusFee)
197195
}
196+
// TODO: send non-surplus fee to a random prefix owner
198197
return parent, onAcceptDB, nil
199198
}
200199

0 commit comments

Comments
 (0)