Skip to content

Commit 5877de8

Browse files
authored
Merge pull request #36 from flare-foundation/Banff_block_support
Banff block support
2 parents 65ebe38 + f0e4e4b commit 5877de8

12 files changed

Lines changed: 129 additions & 39 deletions

File tree

database/pchain_entities.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type PChainTx struct {
2424
Memo string `gorm:"type:varchar(256)"`
2525
Bytes []byte `gorm:"type:mediumblob"`
2626
FeePercentage uint32 // Fee percentage (in case of add validator transaction)
27+
BlockTime *time.Time `gorm:"index"` // Block time, non-null from Banff block activation on (Avalanche 1.9.0)
2728
}
2829

2930
type PChainTxInput struct {

database/types.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,20 @@ const (
1414
type PChainTxType string
1515

1616
const (
17-
PChainRewardValidatorTx PChainTxType = "REWARD_TX"
18-
PChainAddDelegatorTx PChainTxType = "ADD_DELEGATOR_TX"
19-
PChainAddValidatorTx PChainTxType = "ADD_VALIDATOR_TX"
20-
PChainImportTx PChainTxType = "IMPORT_TX"
21-
PChainExportTx PChainTxType = "EXPORT_TX"
22-
PChainAdvanceTimeTx PChainTxType = "ADVANCE_TIME_TX"
23-
PChainCreateChainTx PChainTxType = "CREATE_CHAIN_TX"
24-
PChainCreateSubnetTx PChainTxType = "CREATE_SUBNET_TX"
25-
PChainAddSubnetValidatorTx PChainTxType = "ADD_SUBNET_VALIDATOR_TX"
26-
PChainUnknownTx PChainTxType = "UNKNOWN_TX"
17+
PChainRewardValidatorTx PChainTxType = "REWARD_TX"
18+
PChainAddDelegatorTx PChainTxType = "ADD_DELEGATOR_TX"
19+
PChainAddValidatorTx PChainTxType = "ADD_VALIDATOR_TX"
20+
PChainImportTx PChainTxType = "IMPORT_TX"
21+
PChainExportTx PChainTxType = "EXPORT_TX"
22+
PChainAdvanceTimeTx PChainTxType = "ADVANCE_TIME_TX"
23+
PChainCreateChainTx PChainTxType = "CREATE_CHAIN_TX"
24+
PChainCreateSubnetTx PChainTxType = "CREATE_SUBNET_TX"
25+
PChainAddSubnetValidatorTx PChainTxType = "ADD_SUBNET_VALIDATOR_TX"
26+
PChainRemoveSubnetValidatorTx PChainTxType = "REMOVE_SUBNET_VALIDATOR_TX"
27+
PChainTransformSubnetTx PChainTxType = "TRANSFORM_SUBNET_TX"
28+
PChainAddPermissionlessValidatorTx PChainTxType = "ADD_PERMISSIONLESS_VALIDATOR_TX"
29+
PChainAddPermissionlessDelegatorTx PChainTxType = "ADD_PERMISSIONLESS_DELEGATOR_TX"
30+
PChainUnknownTx PChainTxType = "UNKNOWN_TX"
2731
)
2832

2933
type PChainBlockType string

indexer/context/context.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ type IndexerContext interface {
1616
}
1717

1818
type IndexerFlags struct {
19+
Version bool
20+
1921
ConfigFileName string
2022

2123
// Set start epoch for voting cronjob to this value, overrides config and database value,
@@ -33,8 +35,7 @@ type indexerContext struct {
3335
flags *IndexerFlags
3436
}
3537

36-
func BuildContext() (IndexerContext, error) {
37-
flags := parseIndexerFlags()
38+
func BuildContext(flags *IndexerFlags) (IndexerContext, error) {
3839
cfg, err := config.BuildConfig(flags.ConfigFileName)
3940
if err != nil {
4041
return nil, err
@@ -59,13 +60,15 @@ func (c *indexerContext) DB() *gorm.DB { return c.db }
5960

6061
func (c *indexerContext) Flags() *IndexerFlags { return c.flags }
6162

62-
func parseIndexerFlags() *IndexerFlags {
63+
func ParseIndexerFlags() *IndexerFlags {
64+
versionFlag := flag.Bool("version", false, "Print version information and exit")
6365
cfgFlag := flag.String("config", globalConfig.CONFIG_FILE, "Configuration file (toml format)")
6466
resetVotingFlag := flag.Int64("reset-voting", 0, "Set start epoch for voting cronjob to this value, overrides config and database value, valid values are > 0")
6567
resetMirrorFlag := flag.Int64("reset-mirroring", 0, "Set start epoch for mirroring cronjob to this value, overrides config and database value, valid values are > 0")
6668
flag.Parse()
6769

6870
return &IndexerFlags{
71+
Version: *versionFlag,
6972
ConfigFileName: *cfgFlag,
7073
ResetVotingCronjob: *resetVotingFlag,
7174
ResetMirrorCronjob: *resetMirrorFlag,

indexer/main/indexer.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,21 @@ import (
1313
)
1414

1515
func main() {
16-
ctx, err := context.BuildContext()
16+
flags := context.ParseIndexerFlags()
17+
18+
if flags.Version {
19+
fmt.Printf("Flare P-chain indexer version %s\n", shared.ApplicationVersion)
20+
return
21+
}
22+
23+
ctx, err := context.BuildContext(flags)
1724
if err != nil {
1825
fmt.Printf("%v\n", err)
1926
return
2027
}
28+
29+
logger.Info("Starting Flare indexer application version %s", shared.ApplicationVersion)
30+
2131
err = migrations.Container.ExecuteAll(ctx.DB())
2232
if err != nil {
2333
fmt.Printf("%v\n", err)

indexer/pchain/batch_indexer.go

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import (
1414
"github.com/ava-labs/avalanchego/vms/platformvm/blocks"
1515
"github.com/ava-labs/avalanchego/vms/platformvm/fx"
1616
"github.com/ava-labs/avalanchego/vms/platformvm/txs"
17-
"github.com/ava-labs/avalanchego/vms/proposervm/block"
1817
"gorm.io/gorm"
1918
)
2019

@@ -69,26 +68,37 @@ func (xi *txBatchIndexer) Reset(containerLen int) {
6968
}
7069

7170
func (xi *txBatchIndexer) AddContainer(index uint64, container indexer.Container) error {
72-
blk, err := block.Parse(container.Bytes)
73-
if err != nil {
74-
return err
75-
}
76-
innerBlk, err := blocks.Parse(blocks.GenesisCodec, blk.Block())
71+
innerBlk, err := chain.ParsePChainBlock(container.Bytes)
7772
if err != nil {
7873
return err
7974
}
8075

8176
switch innerBlkType := innerBlk.(type) {
8277
case *blocks.ApricotProposalBlock:
8378
tx := innerBlkType.Tx
84-
err = xi.addTx(&container, database.PChainProposalBlock, innerBlk.Height(), tx)
79+
err = xi.addTx(&container, database.PChainProposalBlock, innerBlk.Height(), 0, tx)
8580
case *blocks.ApricotCommitBlock:
86-
xi.addEmptyTx(&container, database.PChainCommitBlock, innerBlk.Height())
81+
xi.addEmptyTx(&container, database.PChainCommitBlock, innerBlk.Height(), 0)
8782
case *blocks.ApricotAbortBlock:
88-
xi.addEmptyTx(&container, database.PChainAbortBlock, innerBlk.Height())
83+
xi.addEmptyTx(&container, database.PChainAbortBlock, innerBlk.Height(), 0)
8984
case *blocks.ApricotStandardBlock:
9085
for _, tx := range innerBlkType.Txs() {
91-
err = xi.addTx(&container, database.PChainStandardBlock, innerBlk.Height(), tx)
86+
err = xi.addTx(&container, database.PChainStandardBlock, innerBlk.Height(), 0, tx)
87+
if err != nil {
88+
break
89+
}
90+
}
91+
// Banff blocks were introduced in Avalanche 1.9.0
92+
case *blocks.BanffProposalBlock:
93+
tx := innerBlkType.Tx
94+
err = xi.addTx(&container, database.PChainProposalBlock, innerBlk.Height(), innerBlkType.Time, tx)
95+
case *blocks.BanffCommitBlock:
96+
xi.addEmptyTx(&container, database.PChainCommitBlock, innerBlk.Height(), innerBlkType.Time)
97+
case *blocks.BanffAbortBlock:
98+
xi.addEmptyTx(&container, database.PChainAbortBlock, innerBlk.Height(), innerBlkType.Time)
99+
case *blocks.BanffStandardBlock:
100+
for _, tx := range innerBlkType.Txs() {
101+
err = xi.addTx(&container, database.PChainStandardBlock, innerBlk.Height(), innerBlkType.Time, tx)
92102
if err != nil {
93103
break
94104
}
@@ -103,7 +113,7 @@ func (xi *txBatchIndexer) ProcessBatch() error {
103113
return xi.inOutIndexer.ProcessBatch()
104114
}
105115

106-
func (xi *txBatchIndexer) addTx(container *indexer.Container, blockType database.PChainBlockType, height uint64, tx *txs.Tx) error {
116+
func (xi *txBatchIndexer) addTx(container *indexer.Container, blockType database.PChainBlockType, height uint64, blockTime uint64, tx *txs.Tx) error {
107117
txID := tx.ID().String()
108118
dbTx := &database.PChainTx{}
109119
dbTx.TxID = &txID
@@ -112,6 +122,10 @@ func (xi *txBatchIndexer) addTx(container *indexer.Container, blockType database
112122
dbTx.BlockHeight = height
113123
dbTx.Timestamp = chain.TimestampToTime(container.Timestamp)
114124
dbTx.Bytes = container.Bytes
125+
if blockTime != 0 {
126+
time := time.Unix(int64(blockTime), 0)
127+
dbTx.BlockTime = &time
128+
}
115129

116130
var err error = nil
117131
switch unsignedTx := tx.Unsigned.(type) {
@@ -127,26 +141,36 @@ func (xi *txBatchIndexer) addTx(container *indexer.Container, blockType database
127141
err = xi.updateExportTx(dbTx, unsignedTx)
128142
case *txs.AdvanceTimeTx:
129143
xi.updateAdvanceTimeTx(dbTx, unsignedTx)
130-
case *txs.AddSubnetValidatorTx:
131-
err = xi.updateGeneralBaseTx(dbTx, database.PChainAddSubnetValidatorTx, &unsignedTx.BaseTx)
132144
case *txs.CreateChainTx:
133145
err = xi.updateGeneralBaseTx(dbTx, database.PChainCreateChainTx, &unsignedTx.BaseTx)
134146
case *txs.CreateSubnetTx:
135147
err = xi.updateGeneralBaseTx(dbTx, database.PChainCreateSubnetTx, &unsignedTx.BaseTx)
148+
case *txs.RemoveSubnetValidatorTx:
149+
err = xi.updateGeneralBaseTx(dbTx, database.PChainRemoveSubnetValidatorTx, &unsignedTx.BaseTx)
150+
case *txs.TransformSubnetTx:
151+
err = xi.updateGeneralBaseTx(dbTx, database.PChainTransformSubnetTx, &unsignedTx.BaseTx)
152+
// We leave out the following transaction types as they are rejected by Flare nodes
153+
// - AddSubnetValidatorTx
154+
// - AddPermissionlessValidatorTx
155+
// - AddPermissionlessDelegatorTx
136156
default:
137157
err = fmt.Errorf("p-chain transaction %v with type %T in block %d is not indexed", dbTx.TxID, unsignedTx, height)
138158
}
139159
return err
140160
}
141161

142-
func (xi *txBatchIndexer) addEmptyTx(container *indexer.Container, blockType database.PChainBlockType, height uint64) {
162+
func (xi *txBatchIndexer) addEmptyTx(container *indexer.Container, blockType database.PChainBlockType, height uint64, blockTime uint64) {
143163
dbTx := &database.PChainTx{}
144164
dbTx.BlockID = container.ID.String()
145165
dbTx.BlockType = blockType
146166
dbTx.BlockHeight = height
147167
dbTx.Timestamp = chain.TimestampToTime(container.Timestamp)
148168
dbTx.Bytes = container.Bytes
149169
dbTx.TxID = nil
170+
if blockTime != 0 {
171+
time := time.Unix(int64(blockTime), 0)
172+
dbTx.BlockTime = &time
173+
}
150174

151175
xi.newTxs = append(xi.newTxs, dbTx)
152176
}

indexer/pchain/migrations.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
func init() {
1212
migrations.Container.Add("2023-02-10-00-00", "Create initial state for P-Chain transactions", createPChainTxState)
13+
migrations.Container.Add("2024-11-07-00-00", "Alter type column size in p_chain_txes table", alterPChainTxType)
1314
}
1415

1516
func createPChainTxState(db *gorm.DB) error {
@@ -20,3 +21,7 @@ func createPChainTxState(db *gorm.DB) error {
2021
Updated: time.Now(),
2122
})
2223
}
24+
25+
func alterPChainTxType(db *gorm.DB) error {
26+
return db.Exec("ALTER TABLE p_chain_txes CHANGE COLUMN type type VARCHAR(40)").Error
27+
}

indexer/shared/constants.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package shared
2+
3+
const (
4+
ApplicationVersion = "2.0.0"
5+
)

indexer/shared/metrics.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ func InitMetricsServer(cfg *config.MetricsConfig) {
5151

5252
r.Path("/metrics").Handler(promhttp.Handler())
5353
r.Path("/health").HandlerFunc(healthHandler)
54+
r.Path("/version").HandlerFunc(versionHandler)
5455

5556
srv := &http.Server{
5657
Addr: cfg.PrometheusAddress,
@@ -70,6 +71,14 @@ func healthHandler(w http.ResponseWriter, r *http.Request) {
7071
}
7172
}
7273

74+
func versionHandler(w http.ResponseWriter, r *http.Request) {
75+
w.Header().Set("Content-Type", "text/plain")
76+
_, err := w.Write([]byte(ApplicationVersion))
77+
if err != nil {
78+
w.WriteHeader(http.StatusInternalServerError)
79+
}
80+
}
81+
7382
func writeHealthResponse(w http.ResponseWriter) (err error) {
7483
ok, err := getHealthStatus()
7584
if err != nil {

services/api/pchain.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ type ApiPChainTx struct {
1414
StartTime *time.Time `json:"startTime"`
1515
EndTime *time.Time `json:"endTime"`
1616
Weight uint64 `json:"weight"`
17+
BlockTime *time.Time `json:"blockTime"`
1718

1819
Inputs []ApiPChainTxInput `json:"inputs"`
1920
Outputs []ApiPChainTxOutput `json:"outputs"`
@@ -40,6 +41,7 @@ func NewApiPChainTx(tx *database.PChainTx, inputs []database.PChainTxInput, outp
4041
StartTime: tx.StartTime,
4142
EndTime: tx.EndTime,
4243
Weight: tx.Weight,
44+
BlockTime: tx.BlockTime,
4345
Inputs: newApiPChainInputs(inputs),
4446
Outputs: newApiPChainOutputs(outputs),
4547
}

services/main/services.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func main() {
2727
}
2828

2929
muxRouter := mux.NewRouter()
30-
router := utils.NewSwaggerRouter(muxRouter, "Flare P-Chain Indexer", "0.1.0")
30+
router := utils.NewSwaggerRouter(muxRouter, "Flare P-Chain Indexer", "0.1.1")
3131
routes.AddTransferRoutes(router, ctx)
3232
routes.AddStakerRoutes(router, ctx)
3333
routes.AddTransactionRoutes(router, ctx, epochs)

0 commit comments

Comments
 (0)