bridge_transactions.go 4.26 KB
Newer Older
1 2 3 4 5
package database

import (
	"errors"
	"fmt"
Hamdi Allam's avatar
Hamdi Allam committed
6
	"math/big"
7 8 9 10 11 12 13 14 15 16 17 18

	"github.com/google/uuid"
	"gorm.io/gorm"

	"github.com/ethereum/go-ethereum/common"
)

/**
 * Types
 */

type Transaction struct {
Hamdi Allam's avatar
Hamdi Allam committed
19 20
	FromAddress common.Address `gorm:"serializer:bytes"`
	ToAddress   common.Address `gorm:"serializer:bytes"`
Hamdi Allam's avatar
Hamdi Allam committed
21 22
	Amount      *big.Int       `gorm:"serializer:u256"`
	Data        Bytes          `gorm:"serializer:bytes"`
23 24 25 26
	Timestamp   uint64
}

type L1TransactionDeposit struct {
Hamdi Allam's avatar
Hamdi Allam committed
27 28
	SourceHash           common.Hash `gorm:"serializer:bytes;primaryKey"`
	L2TransactionHash    common.Hash `gorm:"serializer:bytes"`
29 30 31
	InitiatedL1EventGUID uuid.UUID

	Tx       Transaction `gorm:"embedded"`
Hamdi Allam's avatar
Hamdi Allam committed
32
	GasLimit *big.Int    `gorm:"serializer:u256"`
33 34 35
}

type L2TransactionWithdrawal struct {
Hamdi Allam's avatar
Hamdi Allam committed
36
	WithdrawalHash       common.Hash `gorm:"serializer:bytes;primaryKey"`
Hamdi Allam's avatar
Hamdi Allam committed
37
	Nonce                *big.Int    `gorm:"serializer:u256"`
38 39 40 41
	InitiatedL2EventGUID uuid.UUID

	ProvenL1EventGUID    *uuid.UUID
	FinalizedL1EventGUID *uuid.UUID
42
	Succeeded            *bool
43 44

	Tx       Transaction `gorm:"embedded"`
Hamdi Allam's avatar
Hamdi Allam committed
45
	GasLimit *big.Int    `gorm:"serializer:u256"`
46 47 48 49 50 51 52 53 54 55
}

type BridgeTransactionsView interface {
	L1TransactionDeposit(common.Hash) (*L1TransactionDeposit, error)
	L2TransactionWithdrawal(common.Hash) (*L2TransactionWithdrawal, error)
}

type BridgeTransactionsDB interface {
	BridgeTransactionsView

56
	StoreL1TransactionDeposits([]L1TransactionDeposit) error
57

58
	StoreL2TransactionWithdrawals([]L2TransactionWithdrawal) error
59
	MarkL2TransactionWithdrawalProvenEvent(common.Hash, uuid.UUID) error
60
	MarkL2TransactionWithdrawalFinalizedEvent(common.Hash, uuid.UUID, bool) error
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
}

/**
 * Implementation
 */

type bridgeTransactionsDB struct {
	gorm *gorm.DB
}

func newBridgeTransactionsDB(db *gorm.DB) BridgeTransactionsDB {
	return &bridgeTransactionsDB{gorm: db}
}

/**
 * Transactions deposited from L1
 */

79
func (db *bridgeTransactionsDB) StoreL1TransactionDeposits(deposits []L1TransactionDeposit) error {
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
	result := db.gorm.Create(&deposits)
	return result.Error
}

func (db *bridgeTransactionsDB) L1TransactionDeposit(sourceHash common.Hash) (*L1TransactionDeposit, error) {
	var deposit L1TransactionDeposit
	result := db.gorm.Where(&L1TransactionDeposit{SourceHash: sourceHash}).Take(&deposit)
	if result.Error != nil {
		if errors.Is(result.Error, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, result.Error
	}

	return &deposit, nil
}

/**
 * Transactions withdrawn from L2
 */

101
func (db *bridgeTransactionsDB) StoreL2TransactionWithdrawals(withdrawals []L2TransactionWithdrawal) error {
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
	result := db.gorm.Create(&withdrawals)
	return result.Error
}

func (db *bridgeTransactionsDB) L2TransactionWithdrawal(withdrawalHash common.Hash) (*L2TransactionWithdrawal, error) {
	var withdrawal L2TransactionWithdrawal
	result := db.gorm.Where(&L2TransactionWithdrawal{WithdrawalHash: withdrawalHash}).Take(&withdrawal)
	if result.Error != nil {
		if errors.Is(result.Error, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, result.Error
	}

	return &withdrawal, nil
}

// MarkL2TransactionWithdrawalProvenEvent links a withdrawn transaction with associated Prove action on L1.
func (db *bridgeTransactionsDB) MarkL2TransactionWithdrawalProvenEvent(withdrawalHash common.Hash, provenL1EventGuid uuid.UUID) error {
	withdrawal, err := db.L2TransactionWithdrawal(withdrawalHash)
	if err != nil {
		return err
Hamdi Allam's avatar
Hamdi Allam committed
124 125
	}
	if withdrawal == nil {
126 127 128 129 130 131 132 133 134
		return fmt.Errorf("transaction withdrawal hash %s not found", withdrawalHash)
	}

	withdrawal.ProvenL1EventGUID = &provenL1EventGuid
	result := db.gorm.Save(&withdrawal)
	return result.Error
}

// MarkL2TransactionWithdrawalProvenEvent links a withdrawn transaction in its finalized state
135
func (db *bridgeTransactionsDB) MarkL2TransactionWithdrawalFinalizedEvent(withdrawalHash common.Hash, finalizedL1EventGuid uuid.UUID, succeeded bool) error {
136 137 138
	withdrawal, err := db.L2TransactionWithdrawal(withdrawalHash)
	if err != nil {
		return err
Hamdi Allam's avatar
Hamdi Allam committed
139 140
	}
	if withdrawal == nil {
141
		return fmt.Errorf("transaction withdrawal hash %s not found", withdrawalHash)
Hamdi Allam's avatar
Hamdi Allam committed
142 143
	}
	if withdrawal.ProvenL1EventGUID == nil {
144 145 146 147
		return fmt.Errorf("cannot mark unproven withdrawal hash %s as finalized", withdrawal.WithdrawalHash)
	}

	withdrawal.FinalizedL1EventGUID = &finalizedL1EventGuid
148
	withdrawal.Succeeded = &succeeded
149 150 151
	result := db.gorm.Save(&withdrawal)
	return result.Error
}