2022-08-23 07:35:50 +00:00
|
|
|
// VulcanizeDB
|
|
|
|
// Copyright © 2022 Vulcanize
|
|
|
|
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU Affero General Public License for more details.
|
|
|
|
|
|
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
2022-06-01 05:59:53 +00:00
|
|
|
package validator
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"github.com/jmoiron/sqlx"
|
|
|
|
)
|
|
|
|
|
2023-06-21 23:25:27 +00:00
|
|
|
var (
|
|
|
|
ReferentialIntegrityErr = "referential integrity check failed at block %d, entry for %s not found"
|
|
|
|
EntryNotFoundErr = "entry for %s not found"
|
|
|
|
)
|
2022-06-01 05:59:53 +00:00
|
|
|
|
2023-06-21 23:25:27 +00:00
|
|
|
// ValidateReferentialIntegrity validates referential integrity at the given height
|
|
|
|
func ValidateReferentialIntegrity(tx *sqlx.Tx, blockNumber uint64) error {
|
|
|
|
err := ValidateHeaderCIDsRef(tx, blockNumber)
|
2022-06-01 05:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-06-21 23:25:27 +00:00
|
|
|
err = ValidateUncleCIDsRef(tx, blockNumber)
|
2022-06-01 05:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-06-21 23:25:27 +00:00
|
|
|
err = ValidateTransactionCIDsRef(tx, blockNumber)
|
2022-06-01 05:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-06-21 23:25:27 +00:00
|
|
|
err = ValidateReceiptCIDsRef(tx, blockNumber)
|
2022-06-01 05:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-06-21 23:25:27 +00:00
|
|
|
err = ValidateStateCIDsRef(tx, blockNumber)
|
2022-06-01 05:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-06-21 23:25:27 +00:00
|
|
|
err = ValidateStorageCIDsRef(tx, blockNumber)
|
2022-06-01 05:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-06-21 23:25:27 +00:00
|
|
|
err = ValidateLogCIDsRef(tx, blockNumber)
|
2022-06-01 05:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ValidateHeaderCIDsRef does a reference integrity check on references in eth.header_cids table
|
2023-06-21 23:25:27 +00:00
|
|
|
func ValidateHeaderCIDsRef(tx *sqlx.Tx, blockNumber uint64) error {
|
|
|
|
err := ValidateIPFSBlocks(tx, blockNumber, "eth.header_cids", "cid")
|
2022-06-01 05:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ValidateUncleCIDsRef does a reference integrity check on references in eth.uncle_cids table
|
2023-06-21 23:25:27 +00:00
|
|
|
func ValidateUncleCIDsRef(tx *sqlx.Tx, blockNumber uint64) error {
|
2022-06-01 05:59:53 +00:00
|
|
|
var exists bool
|
2023-06-21 23:25:27 +00:00
|
|
|
err := tx.Get(&exists, UncleCIDsRefHeaderCIDs, blockNumber)
|
2022-06-01 05:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if exists {
|
|
|
|
return fmt.Errorf(ReferentialIntegrityErr, blockNumber, "eth.header_cids")
|
|
|
|
}
|
|
|
|
|
2023-06-21 23:25:27 +00:00
|
|
|
err = ValidateIPFSBlocks(tx, blockNumber, "eth.uncle_cids", "cid")
|
2022-06-01 05:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ValidateTransactionCIDsRef does a reference integrity check on references in eth.header_cids table
|
2023-06-21 23:25:27 +00:00
|
|
|
func ValidateTransactionCIDsRef(tx *sqlx.Tx, blockNumber uint64) error {
|
2022-06-01 05:59:53 +00:00
|
|
|
var exists bool
|
2023-06-21 23:25:27 +00:00
|
|
|
err := tx.Get(&exists, TransactionCIDsRefHeaderCIDs, blockNumber)
|
2022-06-01 05:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if exists {
|
|
|
|
return fmt.Errorf(ReferentialIntegrityErr, blockNumber, "eth.header_cids")
|
|
|
|
}
|
|
|
|
|
2023-06-21 23:25:27 +00:00
|
|
|
err = ValidateIPFSBlocks(tx, blockNumber, "eth.transaction_cids", "cid")
|
2022-06-01 05:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ValidateReceiptCIDsRef does a reference integrity check on references in eth.receipt_cids table
|
2023-06-21 23:25:27 +00:00
|
|
|
func ValidateReceiptCIDsRef(tx *sqlx.Tx, blockNumber uint64) error {
|
2022-06-01 05:59:53 +00:00
|
|
|
var exists bool
|
2023-06-21 23:25:27 +00:00
|
|
|
err := tx.Get(&exists, ReceiptCIDsRefTransactionCIDs, blockNumber)
|
2022-06-01 05:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if exists {
|
|
|
|
return fmt.Errorf(ReferentialIntegrityErr, blockNumber, "eth.transaction_cids")
|
|
|
|
}
|
|
|
|
|
2023-06-21 23:25:27 +00:00
|
|
|
err = ValidateIPFSBlocks(tx, blockNumber, "eth.receipt_cids", "cid")
|
2022-06-01 05:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ValidateStateCIDsRef does a reference integrity check on references in eth.state_cids table
|
2023-06-21 23:25:27 +00:00
|
|
|
func ValidateStateCIDsRef(tx *sqlx.Tx, blockNumber uint64) error {
|
2022-06-01 05:59:53 +00:00
|
|
|
var exists bool
|
2023-06-21 23:25:27 +00:00
|
|
|
err := tx.Get(&exists, StateCIDsRefHeaderCIDs, blockNumber)
|
2022-06-01 05:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if exists {
|
|
|
|
return fmt.Errorf(ReferentialIntegrityErr, blockNumber, "eth.header_cids")
|
|
|
|
}
|
|
|
|
|
2023-06-21 23:25:27 +00:00
|
|
|
err = ValidateIPFSBlocks(tx, blockNumber, "eth.state_cids", "cid")
|
2022-06-01 05:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ValidateStorageCIDsRef does a reference integrity check on references in eth.storage_cids table
|
2023-06-21 23:25:27 +00:00
|
|
|
func ValidateStorageCIDsRef(tx *sqlx.Tx, blockNumber uint64) error {
|
2022-06-01 05:59:53 +00:00
|
|
|
var exists bool
|
2023-06-21 23:25:27 +00:00
|
|
|
err := tx.Get(&exists, StorageCIDsRefStateCIDs, blockNumber)
|
2022-06-01 05:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if exists {
|
|
|
|
return fmt.Errorf(ReferentialIntegrityErr, blockNumber, "eth.state_cids")
|
|
|
|
}
|
|
|
|
|
2023-06-21 23:25:27 +00:00
|
|
|
err = ValidateIPFSBlocks(tx, blockNumber, "eth.storage_cids", "cid")
|
2022-06-01 05:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ValidateLogCIDsRef does a reference integrity check on references in eth.log_cids table
|
2023-06-21 23:25:27 +00:00
|
|
|
func ValidateLogCIDsRef(tx *sqlx.Tx, blockNumber uint64) error {
|
2022-06-01 05:59:53 +00:00
|
|
|
var exists bool
|
2023-06-21 23:25:27 +00:00
|
|
|
err := tx.Get(&exists, LogCIDsRefReceiptCIDs, blockNumber)
|
2022-06-01 05:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if exists {
|
|
|
|
return fmt.Errorf(ReferentialIntegrityErr, blockNumber, "eth.receipt_cids")
|
|
|
|
}
|
|
|
|
|
2023-06-21 23:25:27 +00:00
|
|
|
err = ValidateIPFSBlocks(tx, blockNumber, "eth.log_cids", "cid")
|
2022-06-01 05:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ValidateIPFSBlocks does a reference integrity check between the given CID table and IPFS blocks table on MHKey and block number
|
2023-06-21 23:25:27 +00:00
|
|
|
func ValidateIPFSBlocks(tx *sqlx.Tx, blockNumber uint64, CIDTable string, CIDField string) error {
|
2022-06-01 05:59:53 +00:00
|
|
|
var exists bool
|
2023-06-21 23:25:27 +00:00
|
|
|
err := tx.Get(&exists, fmt.Sprintf(CIDsRefIPLDBlocks, CIDTable, CIDField), blockNumber)
|
2022-06-01 05:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if exists {
|
2023-06-21 23:25:27 +00:00
|
|
|
return fmt.Errorf(ReferentialIntegrityErr, blockNumber, "ipld.blocks")
|
2022-06-01 05:59:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|