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
134 changes: 113 additions & 21 deletions continuous/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -457,23 +457,40 @@ func queryDecryptionKeysBySlot(blame *ValidatorBlame, cfg *Configuration) error
return nil
}

// buildInnerTxHashToTargetSlotMap creates a map from inner transaction hash to targeted slot
// using the in-memory transactions stored in cfg.status
func buildInnerTxHashToTargetSlotMap(cfg *Configuration) map[string]int64 {
cfg.status.statusModMutex.Lock()
defer cfg.status.statusModMutex.Unlock()

innerTxHashToTargetSlot := make(map[string]int64)

allTxs := append(cfg.status.txInFlight, cfg.status.txDone...)
for _, tx := range allTxs {
if tx.innerTx != nil && tx.targetSlot != 0 {
innerTxHash := tx.innerTx.Hash().Hex()
innerTxHashToTargetSlot[innerTxHash] = tx.targetSlot
}
}
return innerTxHashToTargetSlot
}

func queryStatusRatios(w *bufio.Writer, startBlock, endBlock uint64, cfg *Configuration) error {
queryStatusRatios := `
SELECT
COUNT(*) AS known_tx,
SUM(CASE WHEN dt.tx_status='shielded inclusion' THEN 1.0 END)/COUNT(*) * 100 AS shielded_ratio,
SUM(CASE WHEN dt.tx_status='shielded inclusion' THEN 1 END) AS shielded_amount,
SUM(CASE WHEN dt.tx_status='unshielded inclusion' THEN 1.0 END)/COUNT(*) * 100 AS unshielded_ratio,
SUM(CASE WHEN dt.tx_status='unshielded inclusion' THEN 1 END) AS unshielded_amount,
SUM(CASE WHEN dt.tx_status='not included' THEN 1.0 END)/COUNT(*) * 100 AS not_included_ratio,
SUM(CASE WHEN dt.tx_status='not included' THEN 1 END) not_included_amount,
SUM(CASE WHEN dt.tx_status='pending' THEN 1.0 END)/COUNT(*) * 100 AS pending_ratio,
SUM(CASE WHEN dt.tx_status='pending' THEN 1 END) AS pending_amount
dt.tx_hash,
dt.tx_status,
dt.slot AS inclusion_slot,
b_sequenced.slot AS sequenced_slot
FROM decryption_key AS dk
LEFT JOIN decrypted_tx AS dt
ON dt.decryption_key_id=dk.id
LEFT JOIN block AS b
ON b.slot=dt.slot
LEFT JOIN transaction_submitted_event AS tse
ON tse.id=dt.transaction_submitted_event_id
LEFT JOIN block AS b_sequenced
ON b_sequenced.block_number=tse.event_block_number
WHERE
SUBSTRING(
ENCODE(dk.identity_preimage, 'hex'), --- encode preimage as hex string
Expand All @@ -487,26 +504,101 @@ func queryStatusRatios(w *bufio.Writer, startBlock, endBlock uint64, cfg *Config
return err
}
var count uint64
var shielded, unshielded, notIncluded, pending float64
var shieldedAmount, unshieldedAmount, notIncludedAmount, pendingAmount int64
var shieldedAmount, unshieldedAmount, notIncludedAmount, pendingAmount, inTargetedSlotAmount, invalidForTargetAmount int64

var txHash []byte
var txStatus string
var inclusionSlot *int64
var sequencedSlot *int64

isGraffitiMode := len(cfg.GraffitiSet) > 0
var innerTxHashToTargetSlot map[string]int64
if isGraffitiMode {
innerTxHashToTargetSlot = buildInnerTxHashToTargetSlotMap(cfg)
}

defer rows.Close()
for rows.Next() {
rows.Scan(&count, &shielded, &shieldedAmount, &unshielded, &unshieldedAmount, &notIncluded, &notIncludedAmount, &pending, &pendingAmount)
err = rows.Scan(&txHash, &txStatus, &inclusionSlot, &sequencedSlot)
if err != nil {
log.Printf("Error scanning row: %v", err)
continue
}

count++

// Check if this is a late sequencer transaction (invalid for target)
if isGraffitiMode && sequencedSlot != nil {
txHashHex := common.BytesToHash(txHash).Hex()
targetedSlot, exists := innerTxHashToTargetSlot[txHashHex]
if exists && targetedSlot != 0 && *sequencedSlot >= targetedSlot {
invalidForTargetAmount++
}
}

switch txStatus {
case "shielded inclusion":
shieldedAmount++

_, err = fmt.Fprintf(w,
`%v tx found by observer
// Check if included in targeted slot (only for shielded inclusions and in graffiti mode)
if isGraffitiMode && inclusionSlot != nil {
txHashHex := common.BytesToHash(txHash).Hex()
targetedSlot, exists := innerTxHashToTargetSlot[txHashHex]
if exists && targetedSlot != 0 && *inclusionSlot == targetedSlot {
inTargetedSlotAmount++
}
}
case "unshielded inclusion":
unshieldedAmount++
case "not included":
notIncludedAmount++
case "pending":
pendingAmount++
}
}

if rows.Err() != nil {
return rows.Err()
}

shielded := float64(shieldedAmount) / float64(count) * 100
unshielded := float64(unshieldedAmount) / float64(count) * 100
notIncluded := float64(notIncludedAmount) / float64(count) * 100
pending := float64(pendingAmount) / float64(count) * 100

var inTargetedSlot float64
var invalidForTarget float64
if isGraffitiMode {
inTargetedSlot = float64(inTargetedSlotAmount) / float64(count) * 100
invalidForTarget = float64(invalidForTargetAmount) / float64(count) * 100
}

outputFormat := `%v tx found by observer
%3.2f%% shielded (%v/%v)
%3.2f%% unshielded (%v/%v)
%3.2f%% not included (%v/%v)
%3.2f%% still pending (%v/%v)
`,
count,
shielded, shieldedAmount, count,
unshielded, unshieldedAmount, count,
notIncluded, notIncludedAmount, count,
pending, pendingAmount, count)
`

outputArgs := []interface{}{
count,
shielded, shieldedAmount, count,
unshielded, unshieldedAmount, count,
notIncluded, notIncludedAmount, count,
pending, pendingAmount, count,
}
return nil

// Add targeted slot stat and invalid for target stat only in graffiti mode
if isGraffitiMode {
outputFormat += `
%3.2f%% included in targeted slot (shielded) (%v/%v)
%3.2f%% invalid for target (late sequencer transaction) (%v/%v)`
outputArgs = append(outputArgs, inTargetedSlot, inTargetedSlotAmount, count, invalidForTarget, invalidForTargetAmount, count)
}

_, err = fmt.Fprintf(w, outputFormat+"\n", outputArgs...)

return err
}

func CollectContinuousTestStats(startBlock uint64, endBlock uint64, cache *BlockCache, cfg *Configuration) error {
Expand Down
2 changes: 1 addition & 1 deletion continuous/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func createConfiguration(mode string) (Configuration, error) {
if err != nil {
return cfg, err
}
contracts, err := utils.SetupContracts(client, keyBroadcastAddress, sequencerAddress, keyperSetAddress)
contracts, err := utils.SetupContracts(client, keyBroadcastAddress, sequencerAddress, keyperSetAddress, chainID)
if err != nil {
return cfg, err
}
Expand Down
23 changes: 12 additions & 11 deletions continuous/continuous.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ func (s *Status) AddTxInFlight(t *ShutterTx) {
}

type ShutterBlock struct {
Number int64
Ts pgtype.Date
Number int64
Ts pgtype.Date
TargetedSlot int64
}

func QueryAllShutterBlocks(out chan<- ShutterBlock, cfg *Configuration, mode string) {
Expand Down Expand Up @@ -83,9 +84,9 @@ func QueryAllShutterBlocks(out chan<- ShutterBlock, cfg *Configuration, mode str
out <- newShutterBlock
}
case "graffiti":
newShutterBlock, nextShutterSlot := queryGraffitiNextShutterBlock(status.nextShutterSlot, cfg)
newShutterBlock := queryGraffitiNextShutterBlock(status.nextShutterSlot, cfg)
if !newShutterBlock.Ts.Time.IsZero() {
status.nextShutterSlot = nextShutterSlot
status.nextShutterSlot = newShutterBlock.TargetedSlot
// send event (block number, timestamp) to out channel
out <- newShutterBlock
}
Expand Down Expand Up @@ -133,7 +134,7 @@ func queryNewestShutterBlock(lastBlockTS pgtype.Date, cfg *Configuration) Shutte
return res
}

func queryGraffitiNextShutterBlock(nextShutterSlot int64, cfg *Configuration) (ShutterBlock, int64) {
func queryGraffitiNextShutterBlock(nextShutterSlot int64, cfg *Configuration) (ShutterBlock) {
connection := GetConnection(cfg)

// This query processes the current Shutter block while simultaneously computing
Expand Down Expand Up @@ -192,22 +193,22 @@ func queryGraffitiNextShutterBlock(nextShutterSlot int64, cfg *Configuration) (S
&ts,
)
if err != nil {
return ShutterBlock{}, 0
return ShutterBlock{}
}

// Skip if a block was already returned for the same shutter slot
if nextSlot == nextShutterSlot {
return ShutterBlock{}, 0
// Skip if a block was already returned for the same shutter slot or if there is a consecutive slot
if nextSlot <= nextShutterSlot + 1 {
return ShutterBlock{}
}

if graffiti != "" && cfg.GraffitiSet[graffiti] {
log.Printf(
"Graffiti slot and target block found: nextSlot=%d next_shutter_validator=%d graffiti=%s block=%d ts=%v",
nextSlot, validatorIndex, graffiti, blockNumber, ts.Time,
)
return ShutterBlock{Number: blockNumber, Ts: ts}, nextSlot
return ShutterBlock{Number: blockNumber, Ts: ts, TargetedSlot: nextSlot}
}
return ShutterBlock{}, 0
return ShutterBlock{}
}

func CheckTxInFlight(blockNumber int64, cfg *Configuration) {
Expand Down
4 changes: 3 additions & 1 deletion continuous/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type ShutterTx struct {
submissionBlock int64
inclusionBlock int64
cancelBlock int64
targetSlot int64
txStatus TxStatus
ctx context.Context
cancel context.CancelFunc
Expand Down Expand Up @@ -85,7 +86,7 @@ func (ts TxStatus) String() string {
func (ts TxStatus) EnumIndex() int {
return int(ts)
}
func SendShutterizedTX(blockNumber int64, lastTimestamp pgtype.Date, cfg *Configuration) {
func SendShutterizedTX(blockNumber int64, lastTimestamp pgtype.Date, targetSlot int64, cfg *Configuration) {
account := cfg.NextAccount()
log.Printf("SENDING NEW TX FOR %v from %v", blockNumber, account.Address.Hex())
gasLimit := uint64(21000)
Expand Down Expand Up @@ -155,6 +156,7 @@ func SendShutterizedTX(blockNumber int64, lastTimestamp pgtype.Date, cfg *Config
sender: account,
prefix: identityPrefix,
triggerBlock: blockNumber,
targetSlot: targetSlot,
txStatus: TxStatus(Signed),
ctx: ctx,
cancel: cancel,
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func runContinuous(mode string) {
startBlock = uint64(block.Number)
}
continuous.CheckTxInFlight(block.Number, &cfg)
continuous.SendShutterizedTX(block.Number, block.Ts, &cfg)
continuous.SendShutterizedTX(block.Number, block.Ts, block.TargetedSlot, &cfg)
now := time.Now().Unix()
if now-lastStats > 12 {
log.Println("running stats")
Expand Down
2 changes: 1 addition & 1 deletion stress/stress_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func createSetup(fundNewAccount bool) (utils.StressSetup, error) {
return *setup, err
}

contracts, err := utils.SetupContracts(client, KeyBroadcastContractAddress, SequencerContractAddress, KeyperSetManagerContractAddress)
contracts, err := utils.SetupContracts(client, KeyBroadcastContractAddress, SequencerContractAddress, KeyperSetManagerContractAddress, chainID)
if err != nil {
return *setup, err
}
Expand Down
23 changes: 20 additions & 3 deletions utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,22 @@ type Contracts struct {
depositContractAddress common.Address
}

func SetupContracts(client *ethclient.Client, KeyBroadcastContractAddress, SequencerContractAddress, KeyperSetManagerContractAddress string) (Contracts, error) {
// GetDepositContractAddressByChainID returns the deposit contract address for the given chain ID
// Chain IDs: Gnosis = 100, Chiado = 10200
func GetDepositContractAddressByChainID(chainID *big.Int) (common.Address, error) {
var address common.Address
switch chainID.Uint64() {
case 100: // Gnosis Chain
address = common.HexToAddress("0x0B98057eA310F4d31F2a452B414647007d1645d9")
case 10200: // Chiado
address = common.HexToAddress("0xb97036A26259B7147018913bD58a774cf91acf25")
default:
return address, fmt.Errorf("unsupported chain ID: %v", chainID)
}
return address, nil
}

func SetupContracts(client *ethclient.Client, KeyBroadcastContractAddress, SequencerContractAddress, KeyperSetManagerContractAddress string, chainID *big.Int) (Contracts, error) {
var setup Contracts
keyperSetManagerContract, err := keypersetmanager.NewKeypersetmanager(common.HexToAddress(KeyperSetManagerContractAddress), client)
if err != nil {
Expand All @@ -453,8 +468,10 @@ func SetupContracts(client *ethclient.Client, KeyBroadcastContractAddress, Seque
}

setup.Sequencer = sequencerContract
// depositContractAddress := common.HexToAddress("0x4feF25519256e24A1FC536F7677152dA742Fe3Ef")
depositContractAddress := common.HexToAddress("0x0B98057eA310F4d31F2a452B414647007d1645d9")
depositContractAddress, err := GetDepositContractAddressByChainID(chainID)
if err != nil {
return setup, fmt.Errorf("can not get deposit contract address: %v", err)
}
depositContract, err := NewDepositcontract(depositContractAddress, client)
if err != nil {
return setup, fmt.Errorf("can not get DepositContract %v", err)
Expand Down