Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
stress/pk.hex
*.envrc

pk.hex

# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
Expand Down
2 changes: 2 additions & 0 deletions continuous/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ export CONTINUOUS_DB_NAME=shutter_metrics
export CONTINUOUS_PK_FILE=/home/konrad/Projects/nethermind-tests/pk.hex
# where to store analysis files
export CONTINUOUS_BLAME_FOLDER="/tmp/blame"
# (optional) particular validator indices to monitor (comma-separated list)
export CONTINUOUS_VALIDATOR_INDICES=
```

Make sure, there is an [observer](https://github.com/shutter-network/observer) running and its database accessible as defined in the environment above.
Expand Down
65 changes: 53 additions & 12 deletions continuous/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"log"
"math/big"
"os"
"strconv"
"strings"
"sync"

"github.com/ethereum/go-ethereum/core/types"
Expand All @@ -15,18 +17,19 @@ import (
)

type Configuration struct {
accounts []utils.Account
submitAccount utils.Account
client *ethclient.Client
status Status
contracts utils.Contracts
chainID *big.Int
DbUser string
DbPass string
DbAddr string
DbName string
PkFile string
blameFolder string
accounts []utils.Account
submitAccount utils.Account
client *ethclient.Client
status Status
contracts utils.Contracts
chainID *big.Int
DbUser string
DbPass string
DbAddr string
DbName string
PkFile string
blameFolder string
validatorIndices []int64
Connection
}

Expand Down Expand Up @@ -158,5 +161,43 @@ func createConfiguration() (Configuration, error) {
blameFolder = tmp
}
cfg.blameFolder = blameFolder

// Read validator indices from environment (optional)
validatorIndicesStr := os.Getenv("CONTINUOUS_VALIDATOR_INDICES")
if validatorIndicesStr != "" {
indices, err := parseValidatorIndices(validatorIndicesStr)
if err != nil {
return cfg, fmt.Errorf("could not parse validator indices: %v", err)
}
cfg.validatorIndices = indices
log.Printf("Filtering by validator indices: %v\n", cfg.validatorIndices)
} else {
log.Println("No validator indices specified, running for all shutterized validators")
}

return cfg, nil
}

// parseValidatorIndices parses a comma-separated or space-separated string of validator indices
func parseValidatorIndices(indicesStr string) ([]int64, error) {
// Try comma-separated first, then space-separated
separator := ","
if !strings.Contains(indicesStr, ",") {
separator = " "
}

parts := strings.Split(indicesStr, separator)
var indices []int64
for _, part := range parts {
part = strings.TrimSpace(part)
if part == "" {
continue
}
index, err := strconv.ParseInt(part, 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid validator index '%s': %v", part, err)
}
indices = append(indices, index)
}
return indices, nil
}
81 changes: 74 additions & 7 deletions continuous/continuous.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ const NumFundedAccounts = 6
const MinimalFunding = int64(500000000000000000) // 0.5 ETH in wei

type Status struct {
statusModMutex *sync.Mutex
lastShutterTS pgtype.Date
txInFlight []*ShutterTx
txDone []*ShutterTx
statusModMutex *sync.Mutex
lastShutterTS pgtype.Date
txInFlight []*ShutterTx
txDone []*ShutterTx
currentTargetedShutterSlot int64
}

func (s Status) TxCount() int {
Expand Down Expand Up @@ -71,19 +72,84 @@ func QueryAllShutterBlocks(out chan<- ShutterBlock, cfg *Configuration) {
for {
time.Sleep(waitBetweenQueries)
fmt.Printf(".")
newShutterBlock := queryNewestShutterBlock(status.lastShutterTS, cfg)
newShutterBlock, currentTargetedShutterSlot := queryNewestShutterBlock(status.lastShutterTS, status.currentTargetedShutterSlot, cfg)
if !newShutterBlock.Ts.Time.IsZero() {
status.lastShutterTS = newShutterBlock.Ts
status.currentTargetedShutterSlot = currentTargetedShutterSlot
// send event (block number, timestamp) to out channel
out <- newShutterBlock
}
}
}

func queryNewestShutterBlock(lastBlockTS pgtype.Date, cfg *Configuration) ShutterBlock {
func queryNewestShutterBlock(lastBlockTS pgtype.Date, currentTargetedShutterSlot int64, cfg *Configuration) (ShutterBlock, int64) {
connection := GetConnection(cfg)
block := int64(0)
var ts pgtype.Date

if len(cfg.validatorIndices) > 0 {
query := `
WITH current_block AS (
SELECT
block_number,
slot AS current_slot,
to_timestamp(block_timestamp) AS ts
FROM block
ORDER BY slot DESC
LIMIT 1
),
next_shutter AS (
SELECT
pd.validator_index,
pd.slot AS next_slot
FROM proposer_duties pd
JOIN validator_status vs
ON vs.validator_index = pd.validator_index
WHERE vs.status = 'active_ongoing'
AND pd.slot > (SELECT current_slot FROM current_block)
ORDER BY pd.slot ASC
LIMIT 1
)
SELECT
ns.next_slot,
ns.validator_index,
cb.block_number,
cb.ts
FROM next_shutter ns
JOIN current_block cb ON TRUE
WHERE ns.validator_index = ANY($1);
`

var validatorIndex int64
var nextSlot int64

row := connection.db.QueryRow(
context.Background(),
query,
cfg.validatorIndices,
)

err := row.Scan(&nextSlot, &validatorIndex, &block, &ts)
if err != nil {
return ShutterBlock{}, 0
}

// Skip if we have already targeted this slot
if nextSlot == currentTargetedShutterSlot {
return ShutterBlock{}, 0
}

log.Printf(
"FILTERED FUTURE SHUTTER MATCH: nextSlot=%d next_validator=%d current_block=%d ts=%v",
nextSlot, validatorIndex, block, ts.Time,
)

return ShutterBlock{
Number: block,
Ts: ts,
}, nextSlot
}

query := `
SELECT
b.block_number,
Expand All @@ -97,6 +163,7 @@ func queryNewestShutterBlock(lastBlockTS pgtype.Date, cfg *Configuration) Shutte
AND b.slot = p.slot
AND b.block_timestamp > $1;
`

rows, err := connection.db.Query(context.Background(), query, lastBlockTS.Time.Unix())
if err != nil {
panic(err)
Expand All @@ -117,7 +184,7 @@ func queryNewestShutterBlock(lastBlockTS pgtype.Date, cfg *Configuration) Shutte
res := ShutterBlock{}
res.Number = block
res.Ts = ts
return res
return res, 0
}

func CheckTxInFlight(blockNumber int64, cfg *Configuration) {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ require (
github.com/mmcloughlin/addchain v0.4.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/supranational/blst v0.3.12 // indirect
github.com/supranational/blst v0.3.16 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/supranational/blst v0.3.12 h1:Vfas2U2CFHhniv2QkUm2OVa1+pGTdqtpqm9NnhUUbZ8=
github.com/supranational/blst v0.3.12/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
github.com/supranational/blst v0.3.16 h1:bTDadT+3fK497EvLdWRQEjiGnUtzJ7jjIUMF0jqwYhE=
github.com/supranational/blst v0.3.16/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI=
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48=
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
Expand Down