Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Protobuf] Working prototype #85

Merged
merged 28 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d97753e
actually add protobuf
rpl-ffl Aug 14, 2024
1fb0b27
squash and sign
rpl-ffl Sep 23, 2024
d90279a
revert extraneous line
rpl-ffl Sep 23, 2024
c052aa4
remove extraneous comments + gofmt
rpl-ffl Sep 23, 2024
91394cb
revert uin256, to be separate PR
rpl-ffl Sep 23, 2024
2fe8222
fix extraneous Balance
rpl-ffl Sep 23, 2024
3416551
remove extraneous uint256
rpl-ffl Sep 23, 2024
faeb1eb
decode reverts from uint256 to bigint
rpl-ffl Sep 23, 2024
64f8e8e
remove extranous uint256 import
rpl-ffl Sep 23, 2024
0f6a377
Cleaner GetBlobHash clauses
rpl-ffl Sep 24, 2024
e0d0de9
remove extraneous dangling error
rpl-ffl Sep 25, 2024
ced5262
cleaner explanation when look up initcodehash
rpl-ffl Sep 25, 2024
94a12f2
explain random
rpl-ffl Sep 25, 2024
e655a88
remove substate dump
rpl-ffl Sep 25, 2024
fc7756d
revert extraneous changes
rpl-ffl Sep 25, 2024
bf429ad
Add protobuf encoding test
rpl-ffl Sep 26, 2024
32ce417
encoding now works
rpl-ffl Sep 27, 2024
fd2177c
resolve merge conflict decoderFunc -> decodeFunc
rpl-ffl Sep 27, 2024
942e458
gofmt
rpl-ffl Sep 27, 2024
95d2398
refactor types/utils.go away
rpl-ffl Sep 27, 2024
9485797
protobuf/decode.go
rpl-ffl Sep 27, 2024
c798d75
revert go.mod chnages, geth1.14.8 go1.21
rpl-ffl Sep 30, 2024
79974a4
defensive encoding check removed
rpl-ffl Sep 30, 2024
eeda2a4
remove geth dependency
rpl-ffl Sep 30, 2024
50d95ea
Apply suggestions from code review
rpl-ffl Sep 30, 2024
a660d9b
dbGetCode -> getCodeFunc
rpl-ffl Sep 30, 2024
e68fe3c
encode -> toProtobuf
rpl-ffl Sep 30, 2024
d12af8c
encode -> toProtobufOOO for missing func
rpl-ffl Sep 30, 2024
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
7 changes: 2 additions & 5 deletions db/substate_db.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ import (
"encoding/binary"
"fmt"

"github.com/Fantom-foundation/Substate/rlp"
"github.com/Fantom-foundation/Substate/substate"
trlp "github.com/Fantom-foundation/Substate/types/rlp"
"github.com/syndtr/goleveldb/leveldb"
"github.com/syndtr/goleveldb/leveldb/opt"
"github.com/syndtr/goleveldb/leveldb/util"
Expand Down Expand Up @@ -180,10 +178,9 @@ func (db *substateDB) PutSubstate(ss *substate.Substate) error {

key := SubstateDBKey(ss.Block, ss.Transaction)

substateRLP := rlp.NewRLP(ss)
value, err := trlp.EncodeToBytes(substateRLP)
value, err := db.encodeSubstate(ss, ss.Block, ss.Transaction)
if err != nil {
return fmt.Errorf("cannot encode substate-rlp block %v, tx %v; %v", ss.Block, ss.Transaction, err)
return fmt.Errorf("cannot encode substate block %v, tx %v; %v", ss.Block, ss.Transaction, err)
}

return db.Put(key, value)
Expand Down
2 changes: 1 addition & 1 deletion db/substate_db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ var testSubstate = &substate.Substate{
BaseFee: new(big.Int).SetUint64(1),
},
Message: substate.NewMessage(1, true, new(big.Int).SetUint64(1), 1, types.Address{1}, new(types.Address), new(big.Int).SetUint64(1), []byte{1}, nil, types.AccessList{}, new(big.Int).SetUint64(1), new(big.Int).SetUint64(1), new(big.Int).SetUint64(1), make([]types.Hash, 0)),
Result: substate.NewResult(1, types.Bloom{}, []*types.Log{}, types.Address{1}, 1),
Result: substate.NewResult(1, types.Bloom{}, []*types.Log{}, types.Address{}, 1),
Block: 37_534_834,
Transaction: 1,
}
Expand Down
57 changes: 56 additions & 1 deletion db/substate_encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ package db
import (
"fmt"

pb "github.com/Fantom-foundation/Substate/protobuf"
"github.com/Fantom-foundation/Substate/rlp"
"github.com/Fantom-foundation/Substate/substate"
"github.com/Fantom-foundation/Substate/types"
trlp "github.com/Fantom-foundation/Substate/types/rlp"
"github.com/golang/protobuf/proto"
)

// SetSubstateEncoding sets the runtime encoding/decoding behavior of substateDB
Expand Down Expand Up @@ -35,24 +38,38 @@ func (db *substateDB) GetSubstateEncoding() string {
type substateEncoding struct {
schema string
decode decodeFunc
encode encodeFunc
}

// decodeFunc aliases the common function used to decode substate
type decodeFunc func([]byte, uint64, int) (*substate.Substate, error)

// encodeFunc alias the common function used to encode substate
type encodeFunc func(*substate.Substate, uint64, int) ([]byte, error)

// codeLookupFunc aliases codehash->code lookup necessary to decode substate
type codeLookupFunc = func(types.Hash) ([]byte, error)

// newSubstateDecoder returns requested SubstateDecoder
func newSubstateEncoding(encoding string, lookup codeLookupFunc) (*substateEncoding, error) {
switch encoding {

case "default", "rlp":
case "", "default", "rlp":
return &substateEncoding{
schema: "rlp",
decode: func(bytes []byte, block uint64, tx int) (*substate.Substate, error) {
return decodeRlp(bytes, lookup, block, tx)
},
encode: encodeRlp,
}, nil

case "protobuf", "pb":
return &substateEncoding{
schema: "protobuf",
decode: func(bytes []byte, block uint64, tx int) (*substate.Substate, error) {
return decodeProtobuf(bytes, lookup, block, tx)
},
encode: encodeProtobuf,
}, nil

default:
Expand All @@ -69,6 +86,14 @@ func (db *substateDB) decodeToSubstate(bytes []byte, block uint64, tx int) (*sub
return db.encoding.decode(bytes, block, tx)
}

// encodeSubstate defensively defaults to "default" if nil
func (db *substateDB) encodeSubstate(ss *substate.Substate, block uint64, tx int) ([]byte, error) {
if db.encoding == nil {
db.SetSubstateEncoding("default")
}
return db.encoding.encode(ss, block, tx)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First I think implementation details does not belong to a func comment.
Second, do you think we should have this condition? I think this belongs into the factory func.

Copy link
Collaborator Author

@rpl-ffl rpl-ffl Sep 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defensive defaults now removed in favor of having SetSubstate("default") in all public constructor of substateDB.
79974a4

I understand the performance reason to do this, but this leaves direct instantiation of &substateDB{...} (in tests, for example) to panic if encoding is never set. Any advice on this?


// decodeRlp decodes into substate the provided rlp-encoded bytecode
func decodeRlp(bytes []byte, lookup codeLookupFunc, block uint64, tx int) (*substate.Substate, error) {
rlpSubstate, err := rlp.Decode(bytes)
Expand All @@ -78,3 +103,33 @@ func decodeRlp(bytes []byte, lookup codeLookupFunc, block uint64, tx int) (*subs

return rlpSubstate.ToSubstate(lookup, block, tx)
}

// encodeRlp encodes into rlp-encoded bytes the provided substate
rpl-ffl marked this conversation as resolved.
Show resolved Hide resolved
func encodeRlp(ss *substate.Substate, block uint64, tx int) ([]byte, error) {
bytes, err := trlp.EncodeToBytes(rlp.NewRLP(ss))
if err != nil {
return nil, fmt.Errorf("cannot encode substate into rlp block: %v, tx %v; %w", block, tx, err)
}

return bytes, nil
}

// decodeProtobuf decodes into substate the provided rlp-encoded bytecode
rpl-ffl marked this conversation as resolved.
Show resolved Hide resolved
func decodeProtobuf(bytes []byte, lookup codeLookupFunc, block uint64, tx int) (*substate.Substate, error) {
pbSubstate := &pb.Substate{}
if err := proto.Unmarshal(bytes, pbSubstate); err != nil {
return nil, fmt.Errorf("cannot decode substate data from protobuf block: %v, tx %v; %w", block, tx, err)
}

return pbSubstate.Decode(lookup, block, tx)
}

// encodeRlp encodes into rlp-encoded bytes the provided substate
rpl-ffl marked this conversation as resolved.
Show resolved Hide resolved
func encodeProtobuf(ss *substate.Substate, block uint64, tx int) ([]byte, error) {
bytes, err := proto.Marshal(pb.Encode(ss))
if err != nil {
return nil, fmt.Errorf("cannot encode substate into protobuf block: %v, tx %v; %w", block, tx, err)
}

return bytes, nil
}
98 changes: 60 additions & 38 deletions db/substate_encoding_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,36 @@ import (
"strings"
"testing"

pb "github.com/Fantom-foundation/Substate/protobuf"
"github.com/Fantom-foundation/Substate/rlp"
trlp "github.com/Fantom-foundation/Substate/types/rlp"
"google.golang.org/protobuf/proto"
)

type encTest struct {
bytes []byte
blk uint64
tx int
}

var (
testRlp, _ = trlp.EncodeToBytes(rlp.NewRLP(testSubstate))
testBlk = testSubstate.Block
testTx = testSubstate.Transaction
simplePb, _ = proto.Marshal(pb.Encode(testSubstate))
testPb = encTest{
bytes: simplePb,
blk: testSubstate.Block,
tx: testSubstate.Transaction,
}

simpleRlp, _ = trlp.EncodeToBytes(rlp.NewRLP(testSubstate))
testRlp = encTest{
bytes: simpleRlp,
blk: testSubstate.Block,
tx: testSubstate.Transaction,
}

supportedEncoding = map[string][]byte{
"rlp": testRlp,
supportedEncoding = map[string]encTest{
"rlp": testRlp,
"protobuf": testPb,
}
)

Expand All @@ -30,7 +49,7 @@ func TestSubstateEncoding_NilEncodingDefaultsToRlp(t *testing.T) {
}

// purposely never set encoding
_, err = db.decodeToSubstate(testRlp, testBlk, testTx)
_, err = db.decodeToSubstate(testRlp.bytes, testRlp.blk, testRlp.tx)
if err != nil {
t.Fatal(err)
}
Expand All @@ -41,24 +60,27 @@ func TestSubstateEncoding_NilEncodingDefaultsToRlp(t *testing.T) {
}

func TestSubstateEncoding_DefaultEncodingDefaultsToRlp(t *testing.T) {
path := t.TempDir() + "test-db"
db, err := newSubstateDB(path, nil, nil, nil)
if err != nil {
t.Errorf("cannot open db; %v", err)
}
defaultKeywords := []string{"", "default"}
for _, defaultEncoding := range defaultKeywords {
path := t.TempDir() + "test-db-" + defaultEncoding
db, err := newSubstateDB(path, nil, nil, nil)
if err != nil {
t.Errorf("cannot open db; %v", err)
}

_, err = db.SetSubstateEncoding("default")
if err != nil {
t.Fatal("default is supportet, but error")
}
_, err = db.SetSubstateEncoding(defaultEncoding)
if err != nil {
t.Fatalf("Default encoding '%s' must be supported, but error", defaultEncoding)
}

_, err = db.decodeToSubstate(testRlp, testBlk, testTx)
if err != nil {
t.Fatal(err)
}
_, err = db.decodeToSubstate(testRlp.bytes, testRlp.blk, testRlp.tx)
if err != nil {
t.Fatal(err)
}

if got := db.GetSubstateEncoding(); got != "rlp" {
t.Fatalf("db should default to rlp, got: %s", got)
if got := db.GetSubstateEncoding(); got != "rlp" {
t.Fatalf("db should default to rlp, got: %s", got)
}
}
}

Expand All @@ -76,24 +98,24 @@ func TestSubstateEncoding_UnsupportedEncodingThrowsError(t *testing.T) {
}

func TestSubstateEncoding_TestDb(t *testing.T) {
path := t.TempDir() + "test-db"
db, err := newSubstateDB(path, nil, nil, nil)
if err != nil {
t.Errorf("cannot open db; %v", err)
}
for encoding, et := range supportedEncoding {
path := t.TempDir() + "test-db-" + encoding
db, err := newSubstateDB(path, nil, nil, nil)
if err != nil {
t.Errorf("cannot open db; %v", err)
}

for encoding, bytes := range supportedEncoding {
_, err = db.SetSubstateEncoding(encoding)
db, err = db.SetSubstateEncoding(encoding)
if err != nil {
t.Error(err)
}

ss, err := db.decodeToSubstate(bytes, testBlk, testTx)
ss, err := db.decodeToSubstate(et.bytes, et.blk, et.tx)
if err != nil {
t.Error(err)
}

err = addCustomSubstate(db, testBlk, ss)
err = addCustomSubstate(db, et.blk, ss)
if err != nil {
t.Error(err)
}
Expand All @@ -103,24 +125,24 @@ func TestSubstateEncoding_TestDb(t *testing.T) {
}

func TestSubstateEncoding_TestIterator(t *testing.T) {
path := t.TempDir() + "test-db"
db, err := newSubstateDB(path, nil, nil, nil)
if err != nil {
t.Errorf("cannot open db; %v", err)
}
for encoding, et := range supportedEncoding {
path := t.TempDir() + "test-db-" + encoding
db, err := newSubstateDB(path, nil, nil, nil)
if err != nil {
t.Errorf("cannot open db; %v", err)
}

for encoding, bytes := range supportedEncoding {
_, err = db.SetSubstateEncoding(encoding)
if err != nil {
t.Error(err)
}

ss, err := db.decodeToSubstate(bytes, testBlk, testTx)
ss, err := db.decodeToSubstate(et.bytes, et.blk, et.tx)
if err != nil {
t.Error(err)
}

err = addCustomSubstate(db, testBlk, ss)
err = addCustomSubstate(db, et.blk, ss)
if err != nil {
t.Error(err)
}
Expand Down
23 changes: 15 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
module github.com/Fantom-foundation/Substate

go 1.21
go 1.22

toolchain go1.22.4
rpl-ffl marked this conversation as resolved.
Show resolved Hide resolved

require (
github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954
github.com/urfave/cli/v2 v2.24.4
golang.org/x/crypto v0.17.0
github.com/ethereum/go-ethereum v1.14.9
github.com/golang/protobuf v1.5.4
github.com/holiman/uint256 v1.3.1
github.com/stretchr/testify v1.9.0
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
github.com/urfave/cli/v2 v2.25.7
golang.org/x/crypto v0.22.0
google.golang.org/protobuf v1.34.2
)

require (
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang/snappy v0.0.3 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/stretchr/testify v1.9.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/sys v0.15.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
golang.org/x/sys v0.22.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading