diff --git a/tools/ejections/cmd/main.go b/tools/ejections/cmd/main.go index 31754e029c..dd0afc232e 100644 --- a/tools/ejections/cmd/main.go +++ b/tools/ejections/cmd/main.go @@ -78,13 +78,6 @@ func RunScan(ctx *cli.Context) error { return errors.New("operator ejections not found") } - rowConfigAutoMerge := table.RowConfig{AutoMerge: true} - - operators := table.NewWriter() - operators.AppendHeader(table.Row{"Operator Address", "Quorum", "Stake %", "Timestamp", "Txn"}, rowConfigAutoMerge) - txns := table.NewWriter() - txns.AppendHeader(table.Row{"Txn", "Timestamp", "Operator Address", "Quorum", "Stake %"}, rowConfigAutoMerge) - sort.Slice(ejections, func(i, j int) bool { return ejections[i].BlockTimestamp > ejections[j].BlockTimestamp }) @@ -123,6 +116,17 @@ func RunScan(ctx *cli.Context) error { operatorIdToAddress["0x"+operatorIDs[i].Hex()] = strings.ToLower(operatorAddresses[i].Hex()) } + rowConfigAutoMerge := table.RowConfig{AutoMerge: true} + rowConfigNoAutoMerge := table.RowConfig{AutoMerge: false} + operators := table.NewWriter() + operators.AppendHeader(table.Row{"Operator Address", "Quorum", "Stake %", "Timestamp", "Txn"}, rowConfigAutoMerge) + txns := table.NewWriter() + txns.AppendHeader(table.Row{"Txn", "Timestamp", "Operator Address", "Quorum", "Stake %"}, rowConfigAutoMerge) + txnQuorums := table.NewWriter() + txnQuorums.AppendHeader(table.Row{"Txn", "Quorum", "Stake %", "Operators"}, rowConfigNoAutoMerge) + + quorumEjections := make(map[string]map[uint8]uint8, 0) + quorumEjectionsStakePct := make(map[string]map[uint8]float64, 0) for _, ejection := range ejections { state := stateCache[ejection.BlockNumber-1] opID, err := core.OperatorIDFromHex(ejection.OperatorId) @@ -137,11 +141,28 @@ func RunScan(ctx *cli.Context) error { stakePercentage, _ = new(big.Float).Mul(big.NewFloat(100), new(big.Float).Quo(operatorStake, totalStake)).Float64() } + if _, exists := quorumEjections[ejection.TransactionHash]; !exists { + quorumEjections[ejection.TransactionHash] = make(map[uint8]uint8) + } + quorumEjections[ejection.TransactionHash][ejection.Quorum] += 1 + + if _, exists := quorumEjectionsStakePct[ejection.TransactionHash]; !exists { + quorumEjectionsStakePct[ejection.TransactionHash] = make(map[uint8]float64) + } + quorumEjectionsStakePct[ejection.TransactionHash][ejection.Quorum] += stakePercentage + operatorAddress := operatorIdToAddress[ejection.OperatorId] operators.AppendRow(table.Row{operatorAddress, ejection.Quorum, stakePercentage, ejection.BlockTimestamp, ejection.TransactionHash}, rowConfigAutoMerge) txns.AppendRow(table.Row{ejection.TransactionHash, ejection.BlockTimestamp, operatorAddress, ejection.Quorum, stakePercentage}, rowConfigAutoMerge) } + // aggregate quorum ejections per transaction + for txn, quorums := range quorumEjections { + for quorum := range quorums { + txnQuorums.AppendRow(table.Row{txn, quorum, quorumEjectionsStakePct[txn][quorum], quorumEjections[txn][quorum]}, rowConfigAutoMerge) + } + } + operators.SetAutoIndex(true) operators.SetColumnConfigs([]table.ColumnConfig{ {Number: 1, AutoMerge: true}, @@ -160,7 +181,17 @@ func RunScan(ctx *cli.Context) error { txns.SetStyle(table.StyleLight) txns.Style().Options.SeparateRows = true + txnQuorums.SetAutoIndex(true) + txnQuorums.SetColumnConfigs([]table.ColumnConfig{ + {Number: 1, AutoMerge: true}, + {Number: 2, Align: text.AlignCenter}, + {Number: 4, Align: text.AlignCenter}, + }) + txnQuorums.SetStyle(table.StyleLight) + txnQuorums.Style().Options.SeparateRows = true + fmt.Println(operators.Render()) fmt.Println(txns.Render()) + fmt.Println(txnQuorums.Render()) return nil }