-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathpip11-deterministic-finality-milestones.bats
More file actions
153 lines (127 loc) · 5.35 KB
/
pip11-deterministic-finality-milestones.bats
File metadata and controls
153 lines (127 loc) · 5.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/usr/bin/env bats
# bats file_tags=pos,execution-specs,pip11
# PIP-11: Deterministic Finality via Milestones
# https://github.com/maticnetwork/Polygon-Improvement-Proposals/blob/main/PIPs/PIP-11.md
#
# Bor implements milestone-based finality: the chain is locked at milestone points
# and cannot be reorged beyond them. This enables the "finalized" block tag in
# eth_getBlockByNumber, similar to Ethereum's beacon-chain finality.
setup() {
load "../../../../core/helpers/pos-setup.bash"
pos_setup
}
# bats test_tags=execution-specs,pip11,finality
@test "PIP-11: eth_getBlockByNumber 'finalized' returns a valid block" {
# The "finalized" tag should return a block that has been finalized by
# the milestone mechanism. If not supported, the RPC returns an error.
set +e
local result
result=$(curl -s -X POST -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["finalized",false]}' \
"$L2_RPC_URL")
set -e
# Check for RPC error
local error
error=$(echo "$result" | jq -r '.error.message // empty')
if [[ -n "$error" ]]; then
skip "Node does not support 'finalized' block tag: $error"
fi
# Extract block fields
local block_number
block_number=$(echo "$result" | jq -r '.result.number // empty')
local block_hash
block_hash=$(echo "$result" | jq -r '.result.hash // empty')
if [[ -z "$block_number" || -z "$block_hash" ]]; then
echo "Finalized block response missing number or hash" >&2
echo "Response: $(echo "$result" | jq -c '.result')" >&2
return 1
fi
local block_num_dec
block_num_dec=$(printf "%d" "$block_number")
echo "Finalized block: number=$block_num_dec hash=$block_hash" >&3
if [[ "$block_num_dec" -lt 0 ]]; then
echo "Finalized block number is negative: $block_num_dec" >&2
return 1
fi
}
# bats test_tags=execution-specs,pip11,finality
@test "PIP-11: finalized block number is less than or equal to latest block number" {
# The finalized block must always be at or behind the latest block.
# Finality lags behind the chain tip by the milestone confirmation delay.
set +e
local finalized_result
finalized_result=$(curl -s -X POST -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["finalized",false]}' \
"$L2_RPC_URL")
set -e
local error
error=$(echo "$finalized_result" | jq -r '.error.message // empty')
if [[ -n "$error" ]]; then
skip "Node does not support 'finalized' block tag: $error"
fi
local finalized_hex
finalized_hex=$(echo "$finalized_result" | jq -r '.result.number // empty')
if [[ -z "$finalized_hex" ]]; then
skip "Finalized block response has no number field"
fi
local finalized_dec
finalized_dec=$(printf "%d" "$finalized_hex")
local latest_block
latest_block=$(cast block-number --rpc-url "$L2_RPC_URL")
echo "Finalized: $finalized_dec, Latest: $latest_block" >&3
if [[ "$finalized_dec" -gt "$latest_block" ]]; then
echo "Finalized block ($finalized_dec) is ahead of latest ($latest_block)" >&2
return 1
fi
local lag=$(( latest_block - finalized_dec ))
echo "Finality lag: $lag blocks" >&3
}
# bats test_tags=execution-specs,pip11,finality
@test "PIP-11: finalized block advances as new blocks are produced" {
# Milestone finality means the finalized block should advance over time
# as new milestones are confirmed. Take two samples ~3 seconds apart
# and verify the finalized block number does not go backward.
set +e
local result1
result1=$(curl -s -X POST -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["finalized",false]}' \
"$L2_RPC_URL")
set -e
local error
error=$(echo "$result1" | jq -r '.error.message // empty')
if [[ -n "$error" ]]; then
skip "Node does not support 'finalized' block tag: $error"
fi
local finalized1_hex
finalized1_hex=$(echo "$result1" | jq -r '.result.number // empty')
if [[ -z "$finalized1_hex" ]]; then
skip "Finalized block response has no number field"
fi
local finalized1
finalized1=$(printf "%d" "$finalized1_hex")
# Wait for a few blocks to be produced (~3 seconds at 1s block time)
sleep 3
set +e
local result2
result2=$(curl -s -X POST -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["finalized",false]}' \
"$L2_RPC_URL")
set -e
local finalized2_hex
finalized2_hex=$(echo "$result2" | jq -r '.result.number // empty')
if [[ -z "$finalized2_hex" ]]; then
echo "Second finalized query returned no number" >&2
return 1
fi
local finalized2
finalized2=$(printf "%d" "$finalized2_hex")
echo "Finalized t=0: $finalized1, Finalized t=3s: $finalized2" >&3
# Finalized block must never go backward (no reorg past milestone)
if [[ "$finalized2" -lt "$finalized1" ]]; then
echo "Finalized block went backward: $finalized1 -> $finalized2" >&2
return 1
fi
# On an active chain, finalized should advance (or at least stay the same)
local advance=$(( finalized2 - finalized1 ))
echo "Finalized advanced by $advance blocks in ~3s" >&3
}