db.go 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. package db
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/certusone/wormhole/node/pkg/vaa"
  6. "github.com/dgraph-io/badger/v3"
  7. )
  8. type Database struct {
  9. db *badger.DB
  10. }
  11. type VAAID struct {
  12. EmitterChain vaa.ChainID
  13. EmitterAddress vaa.Address
  14. Sequence uint64
  15. }
  16. func vaaIDFromVAA(v *vaa.VAA) *VAAID {
  17. return &VAAID{
  18. EmitterChain: v.EmitterChain,
  19. EmitterAddress: v.EmitterAddress,
  20. Sequence: v.Sequence,
  21. }
  22. }
  23. var (
  24. ErrVAANotFound = errors.New("requested VAA not found in store")
  25. )
  26. func (i *VAAID) Bytes() []byte {
  27. return []byte(fmt.Sprintf("signed/%d/%s/%d", i.EmitterChain, i.EmitterAddress, i.Sequence))
  28. }
  29. func Open(path string) (*Database, error) {
  30. db, err := badger.Open(badger.DefaultOptions(path))
  31. if err != nil {
  32. return nil, fmt.Errorf("failed to open database: %w", err)
  33. }
  34. return &Database{
  35. db: db,
  36. }, nil
  37. }
  38. func (d *Database) Close() error {
  39. return d.db.Close()
  40. }
  41. func (d *Database) StoreSignedVAA(v *vaa.VAA) error {
  42. if len(v.Signatures) == 0 {
  43. panic("StoreSignedVAA called for unsigned VAA")
  44. }
  45. b, _ := v.Marshal()
  46. // TODO: panic if same VAA is stored with different value
  47. err := d.db.Update(func(txn *badger.Txn) error {
  48. if err := txn.Set(vaaIDFromVAA(v).Bytes(), b); err != nil {
  49. return err
  50. }
  51. return nil
  52. })
  53. if err != nil {
  54. return fmt.Errorf("failed to commit tx: %w", err)
  55. }
  56. return nil
  57. }
  58. func (d *Database) GetSignedVAABytes(id VAAID) (b []byte, err error) {
  59. if err := d.db.View(func(txn *badger.Txn) error {
  60. item, err := txn.Get(id.Bytes())
  61. if err != nil {
  62. return err
  63. }
  64. if val, err := item.ValueCopy(nil); err != nil {
  65. return err
  66. } else {
  67. b = val
  68. }
  69. return nil
  70. }); err != nil {
  71. if err == badger.ErrKeyNotFound {
  72. return nil, ErrVAANotFound
  73. }
  74. return nil, err
  75. }
  76. return
  77. }