-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
241 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package db | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/Fantom-foundation/Substate/rlp" | ||
"github.com/Fantom-foundation/Substate/substate" | ||
"github.com/Fantom-foundation/Substate/types" | ||
) | ||
|
||
// SetSubstateEncoding sets the runtime encoding/decoding behavior of substateDB | ||
// intended usage: | ||
// | ||
// db := &substateDB{..} | ||
// db, err := db.SetSubstateEncoding(<schema>) // set encoding | ||
// db.GetSubstateDecoder() // returns configured encoding | ||
func (db *substateDB) SetSubstateEncoding(schema string) (*substateDB, error) { | ||
encoding, err := newSubstateEncoding(schema, db.GetCode) | ||
if err != nil { | ||
return nil, fmt.Errorf("Failed to set decoder; %w", err) | ||
} | ||
|
||
db.encoding = encoding | ||
return db, nil | ||
} | ||
|
||
// GetDecoder returns the encoding in use | ||
func (db *substateDB) GetSubstateEncoding() string { | ||
if db.encoding == nil { | ||
return "" | ||
} | ||
return db.encoding.schema | ||
} | ||
|
||
type substateEncoding struct { | ||
schema string | ||
decode decoderFunc | ||
} | ||
|
||
// decoderFunc aliases the common function used to decode substate | ||
type decoderFunc func([]byte, uint64, int) (*substate.Substate, error) | ||
|
||
// codeLookup aliases codehash->code lookup necessary to decode substate | ||
type codeLookup = func(types.Hash) ([]byte, error) | ||
|
||
// newSubstateDecoder returns requested SubstateDecoder | ||
func newSubstateEncoding(encoding string, lookup codeLookup) (*substateEncoding, error) { | ||
switch encoding { | ||
|
||
case "default", "rlp": | ||
return &substateEncoding{ | ||
schema: "rlp", | ||
decode: func(bytes []byte, block uint64, tx int) (*substate.Substate, error) { | ||
return decodeRlp(bytes, lookup, block, tx) | ||
}, | ||
}, nil | ||
|
||
default: | ||
return nil, fmt.Errorf("Encoding not supported: %s", encoding) | ||
|
||
} | ||
} | ||
|
||
// decodeSubstate defensively defaults to "default" if nil | ||
func (db *substateDB) decodeToSubstate(bytes []byte, block uint64, tx int) (*substate.Substate, error) { | ||
if db.encoding == nil { | ||
db.SetSubstateEncoding("default") | ||
} | ||
return db.encoding.decode(bytes, block, tx) | ||
} | ||
|
||
// decodeRlp decodes into substate the provided rlp-encoded bytecode | ||
func decodeRlp(bytes []byte, lookup codeLookup, block uint64, tx int) (*substate.Substate, error) { | ||
rlpSubstate, err := rlp.Decode(bytes) | ||
if err != nil { | ||
return nil, fmt.Errorf("cannot decode substate data from rlp block: %v, tx %v; %w", block, tx, err) | ||
} | ||
|
||
return rlpSubstate.ToSubstate(lookup, block, tx) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
package db | ||
|
||
import ( | ||
"strings" | ||
"testing" | ||
|
||
"github.com/Fantom-foundation/Substate/rlp" | ||
trlp "github.com/Fantom-foundation/Substate/types/rlp" | ||
) | ||
|
||
var ( | ||
testRlp, _ = trlp.EncodeToBytes(rlp.NewRLP(testSubstate)) | ||
testBlk = testSubstate.Block | ||
testTx = testSubstate.Transaction | ||
|
||
supportedEncoding = map[string][]byte{ | ||
"rlp": testRlp, | ||
} | ||
) | ||
|
||
func TestSubstateEncoding_NilEncodingDefaultsToRlp(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) | ||
} | ||
|
||
if got := db.GetSubstateEncoding(); got != "" { | ||
t.Fatalf("substate encoding should be nil, got: %s", got) | ||
} | ||
|
||
// purposely never set encoding | ||
_, err = db.decodeToSubstate(testRlp, testBlk, testTx) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
if got := db.GetSubstateEncoding(); got != "rlp" { | ||
t.Fatalf("db should default to rlp, got: %s", got) | ||
} | ||
} | ||
|
||
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) | ||
} | ||
|
||
_, err = db.SetSubstateEncoding("default") | ||
if err != nil { | ||
t.Fatal("default is supportet, but error") | ||
} | ||
|
||
_, err = db.decodeToSubstate(testRlp, testBlk, testTx) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
if got := db.GetSubstateEncoding(); got != "rlp" { | ||
t.Fatalf("db should default to rlp, got: %s", got) | ||
} | ||
} | ||
|
||
func TestSubstateEncoding_UnsupportedEncodingThrowsError(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) | ||
} | ||
|
||
_, err = db.SetSubstateEncoding("EncodingNotSupported") | ||
if err == nil || !strings.Contains(err.Error(), "Encoding not supported") { | ||
t.Error("Encoding not supported, but no error") | ||
} | ||
} | ||
|
||
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, bytes := range supportedEncoding { | ||
_, err = db.SetSubstateEncoding(encoding) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
||
ss, err := db.decodeToSubstate(bytes, testBlk, testTx) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
||
err = addCustomSubstate(db, testBlk, ss) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
||
testSubstateDB_GetSubstate(db, 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, bytes := range supportedEncoding { | ||
_, err = db.SetSubstateEncoding(encoding) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
||
ss, err := db.decodeToSubstate(bytes, testBlk, testTx) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
||
err = addCustomSubstate(db, testBlk, ss) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
||
testSubstatorIterator_Value(db, t) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters