2021-07-30 13:40:01 -07:00
|
|
|
package db
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"github.com/certusone/wormhole/bridge/pkg/vaa"
|
|
|
|
"github.com/dgraph-io/badger/v3"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Database struct {
|
|
|
|
db *badger.DB
|
|
|
|
}
|
|
|
|
|
|
|
|
type VAAID struct {
|
|
|
|
EmitterChain vaa.ChainID
|
|
|
|
EmitterAddress vaa.Address
|
|
|
|
Sequence uint64
|
|
|
|
}
|
|
|
|
|
|
|
|
func vaaIDFromVAA(v *vaa.VAA) *VAAID {
|
|
|
|
return &VAAID{
|
|
|
|
EmitterChain: v.EmitterChain,
|
|
|
|
EmitterAddress: v.EmitterAddress,
|
|
|
|
Sequence: v.Sequence,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
|
|
ErrVAANotFound = errors.New("requested VAA not found in store")
|
|
|
|
)
|
|
|
|
|
|
|
|
func (i *VAAID) Bytes() []byte {
|
|
|
|
return []byte(fmt.Sprintf("signed/%d/%s/%d", i.EmitterChain, i.EmitterAddress, i.Sequence))
|
|
|
|
}
|
|
|
|
|
|
|
|
func Open(path string) (*Database, error) {
|
|
|
|
db, err := badger.Open(badger.DefaultOptions(path))
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to open database: %w", err)
|
|
|
|
}
|
|
|
|
return &Database{
|
|
|
|
db: db,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Database) Close() error {
|
|
|
|
return d.db.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Database) StoreSignedVAA(v *vaa.VAA) error {
|
|
|
|
if len(v.Signatures) == 0 {
|
|
|
|
panic("StoreSignedVAA called for unsigned VAA")
|
|
|
|
}
|
|
|
|
|
|
|
|
b, _ := v.Marshal()
|
|
|
|
|
2021-07-30 17:25:22 -07:00
|
|
|
// TODO: panic if same VAA is stored with different value
|
|
|
|
|
2021-07-30 13:40:01 -07:00
|
|
|
err := d.db.Update(func(txn *badger.Txn) error {
|
|
|
|
if err := txn.Set(vaaIDFromVAA(v).Bytes(), b); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to commit tx: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Database) GetSignedVAABytes(id VAAID) (b []byte, err error) {
|
|
|
|
if err := d.db.View(func(txn *badger.Txn) error {
|
|
|
|
item, err := txn.Get(id.Bytes())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-07-30 17:25:22 -07:00
|
|
|
if val, err := item.ValueCopy(nil); err != nil {
|
2021-07-30 13:40:01 -07:00
|
|
|
return err
|
2021-07-30 17:25:22 -07:00
|
|
|
} else {
|
|
|
|
b = val
|
2021-07-30 13:40:01 -07:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
2021-07-30 17:25:22 -07:00
|
|
|
if err == badger.ErrKeyNotFound {
|
|
|
|
return nil, ErrVAANotFound
|
|
|
|
}
|
2021-07-30 13:40:01 -07:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|