From 884057693fd652baed69e96daaffbcbc8a9afbdf Mon Sep 17 00:00:00 2001 From: Lazy Nina Date: Thu, 1 Feb 2024 13:50:19 -0500 Subject: [PATCH] Add new fields to block and transaction that are introduced w/ pos --- entries/block.go | 71 +++++++++++++----- entries/stake_reward.go | 48 ++++++++++++ entries/transaction.go | 18 ++++- entries/utxo_operation.go | 49 ++++++++++-- main.go | 2 + ...0231213000001_create_stake_entry_table.go} | 0 ...213000002_create_validator_entry_table.go} | 0 ...000003_create_locked_stake_entry_table.go} | 0 ...0240129000003_create_epoch_entry_table.go} | 0 ...00001_update_block_table_with_pos_types.go | 43 +++++++++++ ...update_transaction_table_with_pos_types.go | 30 ++++++++ ...0240212000002_create_stake_reward_table.go | 44 +++++++++++ ...13000001_update_transaction_types_table.go | 37 ++++++++++ .../20240213000002_create_pos_fk_comments.go | 74 +++++++++++++++++++ 14 files changed, 389 insertions(+), 27 deletions(-) create mode 100644 entries/stake_reward.go rename migrations/initial_migrations/{20231213000000_create_stake_entry_table.go => 20231213000001_create_stake_entry_table.go} (100%) rename migrations/initial_migrations/{20231213000000_create_validator_entry_table.go => 20231213000002_create_validator_entry_table.go} (100%) rename migrations/initial_migrations/{20231213000000_create_locked_stake_entry_table.go => 20231213000003_create_locked_stake_entry_table.go} (100%) rename migrations/initial_migrations/{20240129000000_create_epoch_entry_table.go => 20240129000003_create_epoch_entry_table.go} (100%) create mode 100644 migrations/initial_migrations/20240201000001_update_block_table_with_pos_types.go create mode 100644 migrations/initial_migrations/20240201000002_update_transaction_table_with_pos_types.go create mode 100644 migrations/initial_migrations/20240212000002_create_stake_reward_table.go create mode 100644 migrations/initial_migrations/20240213000001_update_transaction_types_table.go create mode 100644 migrations/post_sync_migrations/20240213000002_create_pos_fk_comments.go diff --git a/entries/block.go b/entries/block.go index f9dba54..c20016a 100644 --- a/entries/block.go +++ b/entries/block.go @@ -1,3 +1,5 @@ +//go:build relic + package entries import ( @@ -12,14 +14,23 @@ import ( ) type BlockEntry struct { - BlockHash string `pg:",pk,use_zero"` - PrevBlockHash string - TxnMerkleRoot string - Timestamp time.Time - Height uint64 - Nonce uint64 - ExtraNonce uint64 - BadgerKey []byte `pg:",use_zero"` + BlockHash string `pg:",pk,use_zero"` + PrevBlockHash string + TxnMerkleRoot string + Timestamp time.Time + Height uint64 + Nonce uint64 + ExtraNonce uint64 + BlockVersion uint32 + TxnConnectStatusByIndexHash string `pg:",use_zero"` + ProposerPublicKey string `pg:",use_zero"` + ProposerVotingPublicKey string `pg:",use_zero"` + ProposerRandomSeedSignature string `pg:",use_zero"` + ProposedInView uint64 + ProposerVotePartialSignature string `pg:",use_zero"` + // TODO: Quorum Certificates. Separate entry. + + BadgerKey []byte `pg:",use_zero"` } type PGBlockEntry struct { @@ -28,18 +39,34 @@ type PGBlockEntry struct { } // Convert the UserAssociation DeSo encoder to the PG struct used by bun. -func BlockEncoderToPGStruct(block *lib.MsgDeSoBlock, keyBytes []byte) *PGBlockEntry { +func BlockEncoderToPGStruct(block *lib.MsgDeSoBlock, keyBytes []byte, params *lib.DeSoParams) *PGBlockEntry { blockHash, _ := block.Hash() + var txnConnectStatusByIndexHash string + if block.Header.TxnConnectStatusByIndexHash != nil { + txnConnectStatusByIndexHash = hex.EncodeToString(block.Header.TxnConnectStatusByIndexHash.ToBytes()) + } + var proposerPublicKey string + if block.Header.ProposerPublicKey != nil { + proposerPublicKey = consumer.PublicKeyBytesToBase58Check( + block.Header.ProposerPublicKey.ToBytes(), params) + } return &PGBlockEntry{ BlockEntry: BlockEntry{ - BlockHash: hex.EncodeToString(blockHash[:]), - PrevBlockHash: hex.EncodeToString(block.Header.PrevBlockHash[:]), - TxnMerkleRoot: hex.EncodeToString(block.Header.TransactionMerkleRoot[:]), - Timestamp: consumer.UnixNanoToTime(uint64(block.Header.TstampNanoSecs)), - Height: block.Header.Height, - Nonce: block.Header.Nonce, - ExtraNonce: block.Header.ExtraNonce, - BadgerKey: keyBytes, + BlockHash: hex.EncodeToString(blockHash[:]), + PrevBlockHash: hex.EncodeToString(block.Header.PrevBlockHash[:]), + TxnMerkleRoot: hex.EncodeToString(block.Header.TransactionMerkleRoot[:]), + Timestamp: consumer.UnixNanoToTime(uint64(block.Header.TstampNanoSecs)), + Height: block.Header.Height, + Nonce: block.Header.Nonce, + ExtraNonce: block.Header.ExtraNonce, + BlockVersion: block.Header.Version, + TxnConnectStatusByIndexHash: txnConnectStatusByIndexHash, + ProposerPublicKey: proposerPublicKey, + ProposerVotingPublicKey: block.Header.ProposerVotingPublicKey.ToString(), + ProposerRandomSeedSignature: block.Header.ProposerRandomSeedSignature.ToString(), + ProposedInView: block.Header.ProposedInView, + ProposerVotePartialSignature: block.Header.ProposerVotePartialSignature.ToString(), + BadgerKey: keyBytes, }, } } @@ -77,10 +104,16 @@ func bulkInsertBlockEntry(entries []*lib.StateChangeEntry, db *bun.DB, operation for _, entry := range uniqueBlocks { block := entry.Encoder.(*lib.MsgDeSoBlock) - blockEntry := BlockEncoderToPGStruct(block, entry.KeyBytes) + blockEntry := BlockEncoderToPGStruct(block, entry.KeyBytes, params) pgBlockEntrySlice = append(pgBlockEntrySlice, blockEntry) for jj, transaction := range block.Txns { - pgTransactionEntry, err := TransactionEncoderToPGStruct(transaction, uint64(jj), blockEntry.BlockHash, blockEntry.Height, blockEntry.Timestamp, params) + // Check if the transaction connects or not. + txnConnects := blockEntry.Height < uint64(params.ForkHeights.ProofOfStake2ConsensusCutoverBlockHeight) || + jj == 0 || block.TxnConnectStatusByIndex.Get(jj-1) + pgTransactionEntry, err := TransactionEncoderToPGStruct( + transaction, uint64(jj), blockEntry.BlockHash, blockEntry.Height, blockEntry.Timestamp, txnConnects, + params, + ) if err != nil { return errors.Wrapf(err, "entries.bulkInsertBlockEntry: Problem converting transaction to PG struct") } diff --git a/entries/stake_reward.go b/entries/stake_reward.go new file mode 100644 index 0000000..8b86ec1 --- /dev/null +++ b/entries/stake_reward.go @@ -0,0 +1,48 @@ +package entries + +import ( + "github.com/deso-protocol/core/lib" + "github.com/deso-protocol/state-consumer/consumer" + "github.com/uptrace/bun" +) + +type StakeReward struct { + StakerPKID string `bun:",nullzero"` + ValidatorPKID string `bun:",nullzero"` + RewardMethod lib.StakingRewardMethod // TODO: we probably want this to be human readable? + RewardNanos uint64 `pg:",use_zero"` + IsValidatorCommission bool + BlockHash string + + UtxoOpIndex uint64 `pg:",use_zero"` +} + +type PGStakeReward struct { + bun.BaseModel `bun:"table:stake_reward"` + StakeReward +} + +// Convert the StakeRewardStateChangeMetadata DeSo encoder to the PGStakeReward struct used by bun. +func StakeRewardEncoderToPGStruct( + stakeReward *lib.StakeRewardStateChangeMetadata, + params *lib.DeSoParams, + blockHash string, + utxoOpIndex uint64, +) StakeReward { + pgStakeReward := StakeReward{} + + if stakeReward.StakerPKID != nil { + pgStakeReward.StakerPKID = consumer.PublicKeyBytesToBase58Check((*stakeReward.StakerPKID)[:], params) + } + + if stakeReward.ValidatorPKID != nil { + pgStakeReward.ValidatorPKID = consumer.PublicKeyBytesToBase58Check((*stakeReward.ValidatorPKID)[:], params) + } + + pgStakeReward.RewardMethod = stakeReward.StakingRewardMethod + pgStakeReward.RewardNanos = stakeReward.RewardNanos + pgStakeReward.IsValidatorCommission = stakeReward.IsValidatorCommission + pgStakeReward.BlockHash = blockHash + pgStakeReward.UtxoOpIndex = utxoOpIndex + return pgStakeReward +} diff --git a/entries/transaction.go b/entries/transaction.go index c5fe312..ba6a23b 100644 --- a/entries/transaction.go +++ b/entries/transaction.go @@ -33,7 +33,8 @@ type TransactionEntry struct { IndexInBlock uint64 BlockHeight uint64 Timestamp time.Time `pg:",use_zero"` - BadgerKey []byte `pg:",use_zero"` + Connects bool + BadgerKey []byte `pg:",use_zero"` } type PGTransactionEntry struct { @@ -41,7 +42,15 @@ type PGTransactionEntry struct { TransactionEntry } -func TransactionEncoderToPGStruct(transaction *lib.MsgDeSoTxn, blockIndex uint64, blockHash string, blockHeight uint64, timestamp time.Time, params *lib.DeSoParams) (*PGTransactionEntry, error) { +func TransactionEncoderToPGStruct( + transaction *lib.MsgDeSoTxn, + blockIndex uint64, + blockHash string, + blockHeight uint64, + timestamp time.Time, + connects bool, + params *lib.DeSoParams, +) (*PGTransactionEntry, error) { var txInputs []map[string]string for _, input := range transaction.TxInputs { @@ -86,6 +95,7 @@ func TransactionEncoderToPGStruct(transaction *lib.MsgDeSoTxn, blockIndex uint64 IndexInBlock: blockIndex, BlockHeight: blockHeight, Timestamp: timestamp, + Connects: connects, BadgerKey: transaction.Hash()[:], }, } @@ -127,7 +137,9 @@ func transformTransactionEntry(entries []*lib.StateChangeEntry, params *lib.DeSo for _, entry := range uniqueTransactions { transaction := entry.Encoder.(*lib.MsgDeSoTxn) - transactionEntry, err := TransactionEncoderToPGStruct(transaction, 0, "", 0, time.Now(), params) + // Assuming transactions connect when using this function. We can only + // tell if a transaction connects or not if we have the block. + transactionEntry, err := TransactionEncoderToPGStruct(transaction, 0, "", 0, time.Now(), true, params) if err != nil { return nil, errors.Wrapf(err, "entries.transformAndBulkInsertTransactionEntry: Problem converting transaction to PG struct") } diff --git a/entries/utxo_operation.go b/entries/utxo_operation.go index 6234e84..3281113 100644 --- a/entries/utxo_operation.go +++ b/entries/utxo_operation.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/deso-protocol/core/lib" "github.com/deso-protocol/state-consumer/consumer" + "github.com/golang/glog" "github.com/pkg/errors" "github.com/uptrace/bun" "time" @@ -64,7 +65,7 @@ func ConvertUtxoOperationKeyToBlockHashHex(keyBytes []byte) string { return hex.EncodeToString(keyBytes[1:]) } -// PostBatchOperation is the entry point for processing a batch of post entries. It determines the appropriate handler +// UtxoOperationBatchOperation is the entry point for processing a batch of utxo operations. It determines the appropriate handler // based on the operation type and executes it. func UtxoOperationBatchOperation(entries []*lib.StateChangeEntry, db *bun.DB, params *lib.DeSoParams) error { // We check before we call this function that there is at least one operation type. @@ -92,6 +93,7 @@ func bulkInsertUtxoOperationsEntry(entries []*lib.StateChangeEntry, db *bun.DB, transactionUpdates := make([]*PGTransactionEntry, 0) affectedPublicKeys := make([]*PGAffectedPublicKeyEntry, 0) blockEntries := make([]*PGBlockEntry, 0) + stakeRewardEntries := make([]*PGStakeReward, 0) // Start timer to track how long it takes to insert the entries. start := time.Now() @@ -113,14 +115,18 @@ func bulkInsertUtxoOperationsEntry(entries []*lib.StateChangeEntry, db *bun.DB, blockHash := ConvertUtxoOperationKeyToBlockHashHex(entry.KeyBytes) // Check to see if the state change entry has an attached block. - // Note that this only happens during the iniltial sync, in order to speed up the sync process. + // Note that this only happens during the initial sync, in order to speed up the sync process. if entry.Block != nil { insertTransactions = true block := entry.Block - blockEntry := BlockEncoderToPGStruct(block, entry.KeyBytes) + blockEntry := BlockEncoderToPGStruct(block, entry.KeyBytes, params) blockEntries = append(blockEntries, blockEntry) for ii, txn := range block.Txns { - pgTxn, err := TransactionEncoderToPGStruct(txn, uint64(ii), blockEntry.BlockHash, blockEntry.Height, blockEntry.Timestamp, params) + // Check if the transaction connects or not. + txnConnects := blockEntry.Height < uint64(params.ForkHeights.ProofOfStake2ConsensusCutoverBlockHeight) || + ii == 0 || block.TxnConnectStatusByIndex.Get(ii-1) + pgTxn, err := TransactionEncoderToPGStruct( + txn, uint64(ii), blockEntry.BlockHash, blockEntry.Height, blockEntry.Timestamp, txnConnects, params) if err != nil { return errors.Wrapf(err, "entries.bulkInsertUtxoOperationsEntry: Problem converting transaction to PG struct") } @@ -169,7 +175,7 @@ func bulkInsertUtxoOperationsEntry(entries []*lib.StateChangeEntry, db *bun.DB, if err != nil { return fmt.Errorf("entries.bulkInsertUtxoOperationsEntry: Problem decoding transaction for entry %+v at block height %v", entry, entry.BlockHeight) } - txIndexMetadata, err := consumer.ComputeTransactionMetadata(transaction, blockHash, &lib.DeSoMainnetParams, transaction.TxnFeeNanos, uint64(jj), utxoOps) + txIndexMetadata, err := consumer.ComputeTransactionMetadata(transaction, blockHash, params, transaction.TxnFeeNanos, uint64(jj), utxoOps) if err != nil { return fmt.Errorf("entries.bulkInsertUtxoOperationsEntry: Problem computing transaction metadata for entry %+v at block height %v", entry, entry.BlockHeight) } @@ -216,6 +222,27 @@ func bulkInsertUtxoOperationsEntry(entries []*lib.StateChangeEntry, db *bun.DB, affectedPublicKeys = append(affectedPublicKeys, affectedPublicKeyEntry) } transactionUpdates = append(transactionUpdates, transactions[jj]) + } else if jj == len(transactions) { + // TODO: parse utxo operations for the block level index. + // Examples: deletion of expired nonces, staking rewards (restaked + // + payed to balance), validator jailing, updating validator's + // last active at epoch. + for ii, utxoOp := range utxoOps { + switch utxoOp.Type { + case lib.OperationTypeStakeDistributionRestake, lib.OperationTypeStakeDistributionPayToBalance: + stateChangeMetadata, ok := utxoOp.StateChangeMetadata.(*lib.StakeRewardStateChangeMetadata) + if !ok { + glog.Error("bulkInsertUtxoOperationsEntry: Problem with state change metadata for " + + "stake rewards") + continue + } + stakeReward := PGStakeReward{ + StakeReward: StakeRewardEncoderToPGStruct(stateChangeMetadata, params, blockHash, uint64(ii)), + } + stakeRewardEntries = append(stakeRewardEntries, &stakeReward) + } + } + } } // Print how long it took to insert the entries. @@ -273,6 +300,18 @@ func bulkInsertUtxoOperationsEntry(entries []*lib.StateChangeEntry, db *bun.DB, } fmt.Printf("entries.bulkInsertUtxoOperationsEntry: Inserted %v affected public keys in %v s\n", len(affectedPublicKeys), time.Since(start)) + + start = time.Now() + + // Insert stake rewards into db + if len(stakeRewardEntries) > 0 { + _, err := db.NewInsert().Model(&stakeRewardEntries).On("CONFLICT (block_hash, utxo_op_index) DO UPDATE").Exec(context.Background()) + if err != nil { + return errors.Wrapf(err, "InsertStakeRewards: Problem inserting stake rewards") + } + } + fmt.Printf("entries.bulkInsertUtxoOperationsEntry: Inserted %v stake rewards in %v s\n", len(stakeRewardEntries), time.Since(start)) + return nil } diff --git a/main.go b/main.go index aaaea1c..2e24f0a 100644 --- a/main.go +++ b/main.go @@ -108,6 +108,8 @@ func getConfigValues() (pgURI string, stateChangeDir string, consumerProgressDir if stateChangeDir == "" { stateChangeDir = "/tmp/state-changes" } + // Set the state change dir flag that core uses, so DeSoEncoders properly encode and decode state change metadata. + viper.Set("state-change-dir", stateChangeDir) consumerProgressDir = viper.GetString("CONSUMER_PROGRESS_DIR") if consumerProgressDir == "" { diff --git a/migrations/initial_migrations/20231213000000_create_stake_entry_table.go b/migrations/initial_migrations/20231213000001_create_stake_entry_table.go similarity index 100% rename from migrations/initial_migrations/20231213000000_create_stake_entry_table.go rename to migrations/initial_migrations/20231213000001_create_stake_entry_table.go diff --git a/migrations/initial_migrations/20231213000000_create_validator_entry_table.go b/migrations/initial_migrations/20231213000002_create_validator_entry_table.go similarity index 100% rename from migrations/initial_migrations/20231213000000_create_validator_entry_table.go rename to migrations/initial_migrations/20231213000002_create_validator_entry_table.go diff --git a/migrations/initial_migrations/20231213000000_create_locked_stake_entry_table.go b/migrations/initial_migrations/20231213000003_create_locked_stake_entry_table.go similarity index 100% rename from migrations/initial_migrations/20231213000000_create_locked_stake_entry_table.go rename to migrations/initial_migrations/20231213000003_create_locked_stake_entry_table.go diff --git a/migrations/initial_migrations/20240129000000_create_epoch_entry_table.go b/migrations/initial_migrations/20240129000003_create_epoch_entry_table.go similarity index 100% rename from migrations/initial_migrations/20240129000000_create_epoch_entry_table.go rename to migrations/initial_migrations/20240129000003_create_epoch_entry_table.go diff --git a/migrations/initial_migrations/20240201000001_update_block_table_with_pos_types.go b/migrations/initial_migrations/20240201000001_update_block_table_with_pos_types.go new file mode 100644 index 0000000..a692880 --- /dev/null +++ b/migrations/initial_migrations/20240201000001_update_block_table_with_pos_types.go @@ -0,0 +1,43 @@ +package initial_migrations + +import ( + "context" + "github.com/uptrace/bun" +) + +// TODO: Not nullable fields +func updateBlockTableWithPoSFields(db *bun.DB, tableName string) error { + _, err := db.Exec(` + ALTER TABLE block + ADD COLUMN block_version BIGINT, + ADD COLUMN txn_connect_status_by_index_hash VARCHAR, + ADD COLUMN proposer_public_key VARCHAR, + ADD COLUMN proposer_voting_public_key VARCHAR, + ADD COLUMN proposer_random_seed_signature VARCHAR, + ADD COLUMN proposed_in_view BIGINT, + ADD COLUMN proposer_vote_partial_signature VARCHAR; + `) + // TODO: What other fields do we need indexed? + return err +} + +func init() { + Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error { + return updateBlockTableWithPoSFields(db, "block") + }, func(ctx context.Context, db *bun.DB) error { + _, err := db.Exec(` + ALTER TABLE block + DROP COLUMN block_version, + DROP COLUMN txn_connect_status_by_index_hash, + DROP COLUMN proposer_public_key, + DROP COLUMN proposer_voting_public_key, + DROP COLUMN proposer_random_seed_signature, + DROP COLUMN proposed_in_view, + DROP COLUMN proposer_vote_partial_signature; + `) + if err != nil { + return err + } + return nil + }) +} diff --git a/migrations/initial_migrations/20240201000002_update_transaction_table_with_pos_types.go b/migrations/initial_migrations/20240201000002_update_transaction_table_with_pos_types.go new file mode 100644 index 0000000..93484bc --- /dev/null +++ b/migrations/initial_migrations/20240201000002_update_transaction_table_with_pos_types.go @@ -0,0 +1,30 @@ +package initial_migrations + +import ( + "context" + "github.com/uptrace/bun" +) + +func updateTransactionTableWithPoSFields(db *bun.DB) error { + _, err := db.Exec(` + ALTER TABLE transaction_partitioned + ADD COLUMN connects BOOLEAN DEFAULT TRUE NOT NULL; + `) + // TODO: What other fields do we need indexed? + return err +} + +func init() { + Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error { + return updateTransactionTableWithPoSFields(db) + }, func(ctx context.Context, db *bun.DB) error { + _, err := db.Exec(` + ALTER TABLE transaction_partitioned + DROP COLUMN connects; + `) + if err != nil { + return err + } + return nil + }) +} diff --git a/migrations/initial_migrations/20240212000002_create_stake_reward_table.go b/migrations/initial_migrations/20240212000002_create_stake_reward_table.go new file mode 100644 index 0000000..3d9520a --- /dev/null +++ b/migrations/initial_migrations/20240212000002_create_stake_reward_table.go @@ -0,0 +1,44 @@ +package initial_migrations + +import ( + "context" + "strings" + + "github.com/uptrace/bun" +) + +// TODO: Not nullable fields +func createStakeRewardTable(db *bun.DB, tableName string) error { + _, err := db.Exec(strings.Replace(` + CREATE TABLE {tableName} ( + staker_pkid VARCHAR NOT NULL, + validator_pkid VARCHAR NOT NULL, + reward_method SMALLINT NOT NULL, + reward_nanos BIGINT NOT NULL, + is_validator_commission BOOLEAN NOT NULL, + block_hash VARCHAR NOT NULL, + utxo_op_index BIGINT NOT NULL, + PRIMARY KEY(block_hash, utxo_op_index) + ); + CREATE INDEX {tableName}_validator_pkid_idx ON {tableName} (validator_pkid); + CREATE INDEX {tableName}_staker_pkid_idx ON {tableName} (staker_pkid); + CREATE INDEX {tableName}_block_hash_idx ON {tableName} (block_hash); + CREATE INDEX {tableName}_is_validator_commission_idx ON {tableName} (is_validator_commission); + `, "{tableName}", tableName, -1)) + // TODO: What other fields do we need indexed? + return err +} + +func init() { + Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error { + return createStakeRewardTable(db, "stake_reward") + }, func(ctx context.Context, db *bun.DB) error { + _, err := db.Exec(` + DROP TABLE IF EXISTS stake_reward; + `) + if err != nil { + return err + } + return nil + }) +} diff --git a/migrations/initial_migrations/20240213000001_update_transaction_types_table.go b/migrations/initial_migrations/20240213000001_update_transaction_types_table.go new file mode 100644 index 0000000..6371d33 --- /dev/null +++ b/migrations/initial_migrations/20240213000001_update_transaction_types_table.go @@ -0,0 +1,37 @@ +package initial_migrations + +import ( + "context" + + "github.com/uptrace/bun" +) + +func init() { + Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error { + _, err := db.Exec(` + INSERT INTO transaction_type (type, name) VALUES + (34, 'Register As Validator'), + (35, 'Unregister As Validator'), + (36, 'Stake'), + (37, 'Unstake'), + (38, 'Unlock Stake'), + (39, 'Unjail Validator'), + (40, 'Coin Lockup'), + (41, 'Update Coin Lockup Params'), + (42, 'Coin Lockup Transfer'), + (43, 'Coin Unlock'); + `) + if err != nil { + return err + } + return nil + }, func(ctx context.Context, db *bun.DB) error { + _, err := db.Exec(` + delete from transaction_type where type >= 34 AND type <= 43; + `) + if err != nil { + return err + } + return nil + }) +} diff --git a/migrations/post_sync_migrations/20240213000002_create_pos_fk_comments.go b/migrations/post_sync_migrations/20240213000002_create_pos_fk_comments.go new file mode 100644 index 0000000..d2f0003 --- /dev/null +++ b/migrations/post_sync_migrations/20240213000002_create_pos_fk_comments.go @@ -0,0 +1,74 @@ +package post_sync_migrations + +import ( + "context" + + "github.com/uptrace/bun" +) + +// TODO: revisit access group relationships when we refactor the messaging app to use the graphql API. +func init() { + Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error { + _, err := db.Exec(` + comment on table stake_reward is E'@foreignKey (staker_pkid) references account (pkid)|@foreignFieldName stakeRewards|@fieldName staker\n@foreignKey (validator_pkid) references account (pkid)|@foreignFieldName validatorStakeRewards|@fieldName validator\n@foreignKey (block_hash) references block (block_hash)|@foreignFieldName stakeRewardForBlock|@fieldName block'; + comment on table stake_entry is E'@foreignKey (staker_pkid) references account (pkid)|@foreignFieldName stakeEntries|@fieldName staker\n@foreignKey (validator_pkid) references account (pkid)|@foreignFieldName validatorStakeEntries|@fieldName validatorAccount\n@foreignKey (validator_pkid) references validator_entry (validator_pkid)|@foreignFieldName stakeEntries|@fieldName validatorEntry'; + comment on table validator_entry is E'@unique validator_pkid\n@foreignKey (validator_pkid) references account (pkid)|@foreignFieldName validatorEntry|@fieldName account'; + comment on table locked_stake_entry is E'@foreignKey (staker_pkid) references account (pkid)|@foreignFieldName lockedStakeEntries|@fieldName staker\n@foreignKey (validator_pkid) references account (pkid)|@foreignFieldName validatorLockedStakeEntries|@fieldName validatorAccount\n@foreignKey (validator_pkid) references validator_entry(validator_pkid)|@foreignFieldName validatorLockedStakeEntries|@fieldName validatorEntry'; + comment on table yield_curve_point is E'@foreignKey (profile_pkid) references account (pkid)|@foreignFieldName yieldCurvePoints|@fieldName account'; + comment on table locked_balance_entry is E'@foreignKey (profile_pkid) references account (pkid)|@foreignFieldName profileLockedBalanceEntries|@fieldName profileAccount\n@foreignKey (hodler_pkid) references account (pkid)|@foreignFieldName hodlerLockedBalanceEntries|@fieldName hodlerAccount'; + comment on table block is E'@unique block_hash\n@unique height\n@foreignKey (proposer_public_key) references account (public_key)|@foreignFieldName blocksProposed|@fieldName blockProposer'; + comment on column stake_entry.badger_key is E'@omit'; + comment on column validator_entry.badger_key is E'@omit'; + comment on column locked_stake_entry.badger_key is E'@omit'; + comment on column yield_curve_point.badger_key is E'@omit'; + comment on column locked_balance_entry.badger_key is E'@omit'; + comment on column epoch_entry.badger_key is E'@omit'; + comment on table transaction_partition_34 is E'@omit'; + comment on table transaction_partition_35 is E'@omit'; + comment on table transaction_partition_36 is E'@omit'; + comment on table transaction_partition_37 is E'@omit'; + comment on table transaction_partition_38 is E'@omit'; + comment on table transaction_partition_39 is E'@omit'; + comment on table transaction_partition_40 is E'@omit'; + comment on table transaction_partition_41 is E'@omit'; + comment on table transaction_partition_42 is E'@omit'; + comment on table transaction_partition_43 is E'@omit'; + `) + if err != nil { + return err + } + + return nil + }, func(ctx context.Context, db *bun.DB) error { + _, err := db.Exec(` + comment on table stake_reward is NULL; + comment on table stake_entry is NULL; + comment on table validator_entry is NULL; + comment on table locked_stake_entry is NULL; + comment on table yield_curve_point is NULL; + comment on table locked_balance_entry is NULL; + comment on table block is E'@unique block_hash\n@unique height'; + comment on column stake_entry.badger_key is NULL; + comment on column validator_entry.badger_key is NULL; + comment on column locked_stake_entry.badger_key is NULL; + comment on column yield_curve_point.badger_key is NULL; + comment on column locked_balance_entry.badger_key is NULL; + comment on column epoch_entry.badger_key is NULL; + comment on table transaction_partition_34 is NULL; + comment on table transaction_partition_35 is NULL; + comment on table transaction_partition_36 is NULL; + comment on table transaction_partition_37 is NULL; + comment on table transaction_partition_38 is NULL; + comment on table transaction_partition_39 is NULL; + comment on table transaction_partition_40 is NULL; + comment on table transaction_partition_41 is NULL; + comment on table transaction_partition_42 is NULL; + comment on table transaction_partition_43 is NULL; + `) + if err != nil { + return err + } + + return nil + }) +}