Commit 8f2dcb99 authored by Hamdi Allam's avatar Hamdi Allam

replace json serializer

parent 99a78268
...@@ -18,8 +18,8 @@ import ( ...@@ -18,8 +18,8 @@ import (
*/ */
type BlockHeader struct { type BlockHeader struct {
Hash common.Hash `gorm:"primaryKey;serializer:json"` Hash common.Hash `gorm:"primaryKey;serializer:bytes"`
ParentHash common.Hash `gorm:"serializer:json"` ParentHash common.Hash `gorm:"serializer:bytes"`
Number U256 Number U256
Timestamp uint64 Timestamp uint64
...@@ -50,14 +50,14 @@ type LegacyStateBatch struct { ...@@ -50,14 +50,14 @@ type LegacyStateBatch struct {
// violating the primary key constraint. // violating the primary key constraint.
Index uint64 `gorm:"primaryKey;default:0"` Index uint64 `gorm:"primaryKey;default:0"`
Root common.Hash `gorm:"serializer:json"` Root common.Hash `gorm:"serializer:bytes"`
Size uint64 Size uint64
PrevTotal uint64 PrevTotal uint64
L1ContractEventGUID uuid.UUID L1ContractEventGUID uuid.UUID
} }
type OutputProposal struct { type OutputProposal struct {
OutputRoot common.Hash `gorm:"primaryKey;serializer:json"` OutputRoot common.Hash `gorm:"primaryKey;serializer:bytes"`
L2OutputIndex U256 L2OutputIndex U256
L2BlockNumber U256 L2BlockNumber U256
......
...@@ -16,7 +16,7 @@ import ( ...@@ -16,7 +16,7 @@ import (
*/ */
type BridgeMessage struct { type BridgeMessage struct {
MessageHash common.Hash `gorm:"primaryKey;serializer:json"` MessageHash common.Hash `gorm:"primaryKey;serializer:bytes"`
Nonce U256 Nonce U256
SentMessageEventGUID uuid.UUID SentMessageEventGUID uuid.UUID
...@@ -28,12 +28,12 @@ type BridgeMessage struct { ...@@ -28,12 +28,12 @@ type BridgeMessage struct {
type L1BridgeMessage struct { type L1BridgeMessage struct {
BridgeMessage `gorm:"embedded"` BridgeMessage `gorm:"embedded"`
TransactionSourceHash common.Hash `gorm:"serializer:json"` TransactionSourceHash common.Hash `gorm:"serializer:bytes"`
} }
type L2BridgeMessage struct { type L2BridgeMessage struct {
BridgeMessage `gorm:"embedded"` BridgeMessage `gorm:"embedded"`
TransactionWithdrawalHash common.Hash `gorm:"serializer:json"` TransactionWithdrawalHash common.Hash `gorm:"serializer:bytes"`
} }
type BridgeMessagesView interface { type BridgeMessagesView interface {
......
...@@ -8,7 +8,6 @@ import ( ...@@ -8,7 +8,6 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
) )
/** /**
...@@ -16,16 +15,16 @@ import ( ...@@ -16,16 +15,16 @@ import (
*/ */
type Transaction struct { type Transaction struct {
FromAddress common.Address `gorm:"serializer:json"` FromAddress common.Address `gorm:"serializer:bytes"`
ToAddress common.Address `gorm:"serializer:json"` ToAddress common.Address `gorm:"serializer:bytes"`
Amount U256 Amount U256
Data hexutil.Bytes `gorm:"serializer:json"` Data Bytes `gorm:"serializer:bytes"`
Timestamp uint64 Timestamp uint64
} }
type L1TransactionDeposit struct { type L1TransactionDeposit struct {
SourceHash common.Hash `gorm:"serializer:json;primaryKey"` SourceHash common.Hash `gorm:"serializer:bytes;primaryKey"`
L2TransactionHash common.Hash `gorm:"serializer:json"` L2TransactionHash common.Hash `gorm:"serializer:bytes"`
InitiatedL1EventGUID uuid.UUID InitiatedL1EventGUID uuid.UUID
Tx Transaction `gorm:"embedded"` Tx Transaction `gorm:"embedded"`
...@@ -33,7 +32,7 @@ type L1TransactionDeposit struct { ...@@ -33,7 +32,7 @@ type L1TransactionDeposit struct {
} }
type L2TransactionWithdrawal struct { type L2TransactionWithdrawal struct {
WithdrawalHash common.Hash `gorm:"serializer:json;primaryKey"` WithdrawalHash common.Hash `gorm:"serializer:bytes;primaryKey"`
Nonce U256 Nonce U256
InitiatedL2EventGUID uuid.UUID InitiatedL2EventGUID uuid.UUID
......
...@@ -19,12 +19,12 @@ var ( ...@@ -19,12 +19,12 @@ var (
*/ */
type TokenPair struct { type TokenPair struct {
LocalTokenAddress common.Address `gorm:"serializer:json"` LocalTokenAddress common.Address `gorm:"serializer:bytes"`
RemoteTokenAddress common.Address `gorm:"serializer:json"` RemoteTokenAddress common.Address `gorm:"serializer:bytes"`
} }
type BridgeTransfer struct { type BridgeTransfer struct {
CrossDomainMessageHash *common.Hash `gorm:"serializer:json"` CrossDomainMessageHash *common.Hash `gorm:"serializer:bytes"`
Tx Transaction `gorm:"embedded"` Tx Transaction `gorm:"embedded"`
TokenPair TokenPair `gorm:"embedded"` TokenPair TokenPair `gorm:"embedded"`
...@@ -32,27 +32,27 @@ type BridgeTransfer struct { ...@@ -32,27 +32,27 @@ type BridgeTransfer struct {
type L1BridgeDeposit struct { type L1BridgeDeposit struct {
BridgeTransfer `gorm:"embedded"` BridgeTransfer `gorm:"embedded"`
TransactionSourceHash common.Hash `gorm:"primaryKey;serializer:json"` TransactionSourceHash common.Hash `gorm:"primaryKey;serializer:bytes"`
} }
type L1BridgeDepositWithTransactionHashes struct { type L1BridgeDepositWithTransactionHashes struct {
L1BridgeDeposit L1BridgeDeposit `gorm:"embedded"` L1BridgeDeposit L1BridgeDeposit `gorm:"embedded"`
L1TransactionHash common.Hash `gorm:"serializer:json"` L1TransactionHash common.Hash `gorm:"serializer:bytes"`
L2TransactionHash common.Hash `gorm:"serializer:json"` L2TransactionHash common.Hash `gorm:"serializer:bytes"`
} }
type L2BridgeWithdrawal struct { type L2BridgeWithdrawal struct {
BridgeTransfer `gorm:"embedded"` BridgeTransfer `gorm:"embedded"`
TransactionWithdrawalHash common.Hash `gorm:"primaryKey;serializer:json"` TransactionWithdrawalHash common.Hash `gorm:"primaryKey;serializer:bytes"`
} }
type L2BridgeWithdrawalWithTransactionHashes struct { type L2BridgeWithdrawalWithTransactionHashes struct {
L2BridgeWithdrawal L2BridgeWithdrawal `gorm:"embedded"` L2BridgeWithdrawal L2BridgeWithdrawal `gorm:"embedded"`
L2TransactionHash common.Hash `gorm:"serializer:json"` L2TransactionHash common.Hash `gorm:"serializer:bytes"`
ProvenL1TransactionHash common.Hash `gorm:"serializer:json"` ProvenL1TransactionHash common.Hash `gorm:"serializer:bytes"`
FinalizedL1TransactionHash common.Hash `gorm:"serializer:json"` FinalizedL1TransactionHash common.Hash `gorm:"serializer:bytes"`
} }
type BridgeTransfersView interface { type BridgeTransfersView interface {
......
...@@ -21,12 +21,12 @@ type ContractEvent struct { ...@@ -21,12 +21,12 @@ type ContractEvent struct {
GUID uuid.UUID `gorm:"primaryKey"` GUID uuid.UUID `gorm:"primaryKey"`
// Some useful derived fields // Some useful derived fields
BlockHash common.Hash `gorm:"serializer:json"` BlockHash common.Hash `gorm:"serializer:bytes"`
ContractAddress common.Address `gorm:"serializer:json"` ContractAddress common.Address `gorm:"serializer:bytes"`
TransactionHash common.Hash `gorm:"serializer:json"` TransactionHash common.Hash `gorm:"serializer:bytes"`
LogIndex uint64 LogIndex uint64
EventSignature common.Hash `gorm:"serializer:json"` EventSignature common.Hash `gorm:"serializer:bytes"`
Timestamp uint64 Timestamp uint64
// NOTE: NOT ALL THE DERIVED FIELDS ON `types.Log` ARE // NOTE: NOT ALL THE DERIVED FIELDS ON `types.Log` ARE
......
...@@ -5,6 +5,8 @@ import ( ...@@ -5,6 +5,8 @@ import (
"fmt" "fmt"
"github.com/ethereum-optimism/optimism/indexer/config" "github.com/ethereum-optimism/optimism/indexer/config"
_ "github.com/ethereum-optimism/optimism/indexer/database/serializers"
"gorm.io/driver/postgres" "gorm.io/driver/postgres"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/logger" "gorm.io/gorm/logger"
......
package serializers
import (
"context"
"errors"
"fmt"
"reflect"
"github.com/ethereum/go-ethereum/common/hexutil"
"gorm.io/gorm/schema"
)
type BytesSerializer struct{}
type BytesInterface interface{ Bytes() []byte }
type SetBytesInterface interface{ SetBytes([]byte) }
func init() {
schema.RegisterSerializer("bytes", BytesSerializer{})
}
func (BytesSerializer) Scan(ctx context.Context, field *schema.Field, dst reflect.Value, dbValue interface{}) error {
// Empty slices are serialized as '0x'
if dbValue == nil {
return errors.New("cannot unmarshal an empty dbValue")
}
hexStr, ok := dbValue.(string)
if !ok {
return fmt.Errorf("expected hex string as the database value: %T", dbValue)
}
b, err := hexutil.Decode(hexStr)
if err != nil {
return fmt.Errorf("failed to decode database value: %s", err)
}
fieldValue := reflect.New(field.FieldType)
if field.FieldType.Kind() == reflect.Pointer {
// Allocate memory if this is pointer which by
// default when deserializing is probably `nil`
fieldValue.Set(reflect.New(field.FieldType.Elem()))
}
fieldInterface := fieldValue.Interface()
fieldSetBytes, ok := fieldInterface.(SetBytesInterface)
if !ok {
return fmt.Errorf("field does not satisfy the `SetBytes([]byte)` interface: %T", fieldInterface)
}
fieldSetBytes.SetBytes(b)
field.ReflectValueOf(ctx, dst).Set(fieldValue.Elem())
return nil
}
func (BytesSerializer) Value(ctx context.Context, field *schema.Field, dst reflect.Value, fieldValue interface{}) (interface{}, error) {
fieldBytes, ok := fieldValue.(BytesInterface)
if !ok {
return nil, fmt.Errorf("field does not satisfy the `Bytes() []byte` interface")
}
var b []byte
if fieldValue != nil && reflect.ValueOf(fieldValue).IsNil() {
b = fieldBytes.Bytes()
}
hexStr := hexutil.Encode(b)
return hexStr, nil
}
package database package serializers
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"reflect" "reflect"
...@@ -13,38 +14,35 @@ import ( ...@@ -13,38 +14,35 @@ import (
type RLPSerializer struct{} type RLPSerializer struct{}
type RLPInterface interface {
rlp.Encoder
rlp.Decoder
}
func init() { func init() {
schema.RegisterSerializer("rlp", RLPSerializer{}) schema.RegisterSerializer("rlp", RLPSerializer{})
} }
func (RLPSerializer) Scan(ctx context.Context, field *schema.Field, dst reflect.Value, dbValue interface{}) error { func (RLPSerializer) Scan(ctx context.Context, field *schema.Field, dst reflect.Value, dbValue interface{}) error {
// RLP encoding never results in nil bytes
if dbValue == nil {
return errors.New("cannot unmarshal an empty dbValue")
}
hexStr, ok := dbValue.(string)
if !ok {
return fmt.Errorf("expected hex string as the database value: %T", dbValue)
}
b, err := hexutil.Decode(hexStr)
if err != nil {
return fmt.Errorf("failed to decode database value: %s", err)
}
fieldValue := reflect.New(field.FieldType) fieldValue := reflect.New(field.FieldType)
if dbValue != nil { if field.FieldType.Kind() == reflect.Pointer {
var bytes []byte // Allocate memory if this is pointer which by
switch v := dbValue.(type) { // default when deserializing is probably `nil`
case []byte: fieldValue.Set(reflect.New(field.FieldType.Elem()))
bytes = v }
case string:
b, err := hexutil.Decode(v)
if err != nil {
return err
}
bytes = b
default:
return fmt.Errorf("unrecognized RLP bytes: %#v", dbValue)
}
if len(bytes) > 0 { if err := rlp.DecodeBytes(b, fieldValue.Interface()); err != nil {
err := rlp.DecodeBytes(bytes, fieldValue.Interface()) return fmt.Errorf("failed to decode rlp bytes: %s", err)
if err != nil {
return err
}
}
} }
field.ReflectValueOf(ctx, dst).Set(fieldValue.Elem()) field.ReflectValueOf(ctx, dst).Set(fieldValue.Elem())
...@@ -52,18 +50,11 @@ func (RLPSerializer) Scan(ctx context.Context, field *schema.Field, dst reflect. ...@@ -52,18 +50,11 @@ func (RLPSerializer) Scan(ctx context.Context, field *schema.Field, dst reflect.
} }
func (RLPSerializer) Value(ctx context.Context, field *schema.Field, dst reflect.Value, fieldValue interface{}) (interface{}, error) { func (RLPSerializer) Value(ctx context.Context, field *schema.Field, dst reflect.Value, fieldValue interface{}) (interface{}, error) {
// Even though rlp.Encode takes an interface and will error out if the passed interface does not
// satisfy the interface, we check here since we also want to make sure this type satisfies the
// rlp.Decoder interface as well
i := reflect.TypeOf(new(RLPInterface)).Elem()
if !reflect.TypeOf(fieldValue).Implements(i) {
return nil, fmt.Errorf("%T does not satisfy RLP Encoder & Decoder interface", fieldValue)
}
rlpBytes, err := rlp.EncodeToBytes(fieldValue) rlpBytes, err := rlp.EncodeToBytes(fieldValue)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("failed to encode rlp bytes: %s", err)
} }
return hexutil.Bytes(rlpBytes).MarshalText() hexStr := hexutil.Encode(rlpBytes)
return hexStr, nil
} }
...@@ -93,3 +93,12 @@ func (h *RLPHeader) Header() *types.Header { ...@@ -93,3 +93,12 @@ func (h *RLPHeader) Header() *types.Header {
func (h *RLPHeader) Hash() common.Hash { func (h *RLPHeader) Hash() common.Hash {
return h.Header().Hash() return h.Header().Hash()
} }
type Bytes []byte
func (b Bytes) Bytes() []byte {
return b[:]
}
func (b *Bytes) SetBytes(bytes []byte) {
*b = bytes
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment