Skip to content

Commit af4c2f1

Browse files
committed
Merge branch 'staging' into fix/aggregation-contract-verify-elfs
2 parents 4567c2e + 2ff8262 commit af4c2f1

File tree

20 files changed

+270
-25
lines changed

20 files changed

+270
-25
lines changed

Makefile

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,13 +166,17 @@ is_aggregator_set:
166166
exit 1; \
167167
fi
168168

169-
start_proof_aggregator_dev: is_aggregator_set ## Starts proof aggregator with mock proofs (DEV mode)
169+
reset_last_aggregated_block:
170+
@echo "Resetting last aggregated block..."
171+
@echo '{"last_aggregated_block":0}' > config-files/proof-aggregator.last_aggregated_block.json
172+
173+
start_proof_aggregator_dev: is_aggregator_set reset_last_aggregated_block ## Starts proof aggregator with mock proofs (DEV mode)
170174
AGGREGATOR=$(AGGREGATOR) RISC0_DEV_MODE=1 cargo run --manifest-path ./aggregation_mode/Cargo.toml --release --bin proof_aggregator -- config-files/config-proof-aggregator-mock.yaml
171175

172-
start_proof_aggregator: is_aggregator_set ## Starts proof aggregator with proving activated
176+
start_proof_aggregator: is_aggregator_set reset_last_aggregated_block ## Starts proof aggregator with proving activated
173177
AGGREGATOR=$(AGGREGATOR) cargo run --manifest-path ./aggregation_mode/Cargo.toml --release --features prove --bin proof_aggregator -- config-files/config-proof-aggregator.yaml
174178

175-
start_proof_aggregator_gpu: is_aggregator_set ## Starts proof aggregator with proving + GPU acceleration (CUDA)
179+
start_proof_aggregator_gpu: is_aggregator_set reset_last_aggregated_block ## Starts proof aggregator with proving + GPU acceleration (CUDA)
176180
AGGREGATOR=$(AGGREGATOR) SP1_PROVER=cuda cargo run --manifest-path ./aggregation_mode/Cargo.toml --release --features prove,gpu --bin proof_aggregator -- config-files/config-proof-aggregator.yaml
177181

178182
verify_aggregated_proof_sp1_holesky_stage:

aggregation_mode/build.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,28 @@
1+
use risc0_build::{DockerOptionsBuilder, GuestOptionsBuilder};
2+
use std::collections::HashMap;
3+
4+
// Reference: https://docs.succinct.xyz/docs/sp1/writing-programs/compiling#advanced-build-options-1
15
fn main() {
26
sp1_build::build_program_with_args("./aggregation_programs/sp1", {
37
sp1_build::BuildArgs {
48
output_directory: Some("./aggregation_programs/sp1/elf".to_string()),
9+
// We use Docker to generate a reproducible ELF that will be identical across all platforms
10+
// (https://docs.succinct.xyz/docs/sp1/writing-programs/compiling#production-builds)
11+
docker: true,
512
..Default::default()
613
}
714
});
815

9-
risc0_build::embed_methods();
16+
// With this containerized build process, we ensure that all builds of the guest code,
17+
// regardless of the machine or local environment, will produce the same ImageID
18+
let docker_options = DockerOptionsBuilder::default().build().unwrap();
19+
// Reference: https://github.com/risc0/risc0/blob/main/risc0/build/src/config.rs#L73-L90
20+
let guest_options = GuestOptionsBuilder::default()
21+
.use_docker(docker_options)
22+
.build()
23+
.unwrap();
24+
risc0_build::embed_methods_with_options(HashMap::from([(
25+
"risc0_aggregation_program",
26+
guest_options,
27+
)]));
1028
}

alerts/.env.example

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,16 @@ NETWORK=<NETWORK>
3232
PRIVATE_KEY=<SENDER_PRIVATE_KEY>
3333
VERIFICATION_WAIT_TIME=<TIME_TO_WAIT_FOR_VERIFICATION>
3434
LOGS_BLOCK_RANGE=<LOGS_BLOCK_RANGE>
35+
36+
# Variables for aggregation_mode_alerts.sh
37+
CONTRACT_ADDRESS=<YOUR_CONTRACT_ADDRESS>
38+
AGGREGATED_PROOF_VERIFIED_TOPIC=0xfe3e9e971000ab9c80c7e06aba2933aae5419d0e44693e3046913e9e58053f62
39+
RPC_URL=<YOUR_RPC_URL>
40+
LOGS_BLOCK_RANGE=7500
41+
SLEEP_TIME=3600
42+
PAGER_DUTY_KEY=<YOUR_PAGER_DUTY_KEY>
43+
PAGER_DUTY_EMAIL=<YOUR_PAGER_DUTY_EMAIL>
44+
PAGER_DUTY_SERVICE_ID=<YOUR_PAGER_DUTY_SERVICE_ID>
45+
SLACK_WEBHOOK_URL=<YOUR_SLACK_WEBHOOK_URL>
46+
TELEGRAM_BOT_TOKEN=<YOUR_TELEGRAM_BOT_TOKEN>
47+
TELEGRAM_CHAT_ID=<YOUR_TELEGRAM_CHAT_ID>

alerts/aggregation_mode_alerts.sh

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#!/bin/bash
2+
3+
# ENV_VARIABLES
4+
#
5+
# - CONTRACT_ADDRESS
6+
# - Holesky: 0xe84CD4084d8131841CE6DC265361f81F4C59a1d4
7+
# - Stage: 0x7Eace34A8d4C4CacE633946C6F7CF4BeF3F33513
8+
# - AGGREGATED_PROOF_VERIFIED_TOPIC (0xfe3e9e971000ab9c80c7e06aba2933aae5419d0e44693e3046913e9e58053f62)
9+
# - RPC_URL
10+
# - LOGS_BLOCK_RANGE (25hs -> 7500 blocks)
11+
# - SLEEP_TIME
12+
# - PAGER_DUTY_KEY
13+
# - PAGER_DUTY_EMAIL
14+
# - PAGER_DUTY_SERVICE_ID
15+
# - SLACK_WEBHOOK_URL
16+
# - TELEGRAM_CHAT_ID
17+
# - TELEGRAM_BOT_TOKEN
18+
19+
# Load env file from $1 path
20+
source "$1"
21+
22+
# Function to send slack message
23+
# @param message
24+
function send_slack_message() {
25+
. alerts/slack.sh "$1"
26+
}
27+
28+
# Function to send telegram message
29+
# @param message
30+
function send_telegram_message() {
31+
. alerts/telegram.sh "$1"
32+
}
33+
34+
# Function to send PagerDuty alert
35+
# @param message
36+
function send_pagerduty_alert() {
37+
. alerts/pagerduty.sh "$1"
38+
}
39+
40+
# Flags to avoid sending multiple alerts
41+
no_new_aggregation_alert=false
42+
43+
while :
44+
do
45+
last_block=$(cast block --rpc-url $RPC_URL -f number)
46+
printf "Last block: %s\n" $last_block
47+
48+
from_block=$(($last_block - $LOGS_BLOCK_RANGE))
49+
50+
new_aggregated_proofs_logs=$(cast logs --rpc-url $RPC_URL --from-block $from_block --address $CONTRACT_ADDRESS $AGGREGATED_PROOF_VERIFIED_TOPIC)
51+
if [ -z "$new_aggregated_proofs_logs" ]; then
52+
printf "No new aggregated proofs logs found\n"
53+
if [ "$no_new_aggregation_alert" = false ]; then
54+
message="🚨 $NETWORK ALERT Aggregation Mode: No new aggregated proofs since block $from_block"
55+
printf "$message\n"
56+
send_slack_message "$message"
57+
send_telegram_message "$message"
58+
send_pagerduty_alert "$message"
59+
fi
60+
no_new_aggregation_alert=true
61+
else
62+
printf "New aggregated proofs logs found\n"
63+
if [ "$no_new_aggregation_alert" = true ]; then
64+
message="🟩 $NETWORK INFO Aggregation Mode: Aggregated proofs creation resumed since block $from_block"
65+
printf "$message\n"
66+
send_slack_message "$message"
67+
send_telegram_message "$message"
68+
fi
69+
no_new_aggregation_alert=false
70+
fi
71+
72+
sleep $SLEEP_TIME
73+
done

alerts/telegram.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Function to send telegram message
2+
# @param message
3+
curl -s -X POST https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage \
4+
-d chat_id=$TELEGRAM_CHAT_ID \
5+
-d text="$1" \
6+
-d disable_notification=true
7+

explorer/lib/explorer/contract_managers/aligned_proof_aggregation_service.ex

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ defmodule AlignedProofAggregationService do
22
require Logger
33

44
@aligned_config_file System.get_env("ALIGNED_PROOF_AGG_CONFIG_FILE")
5+
@verifyRisc0_solidity_signature "0x015f8668"
6+
@verifySp1_solidity_signature "0x39c94cbf"
57

68
config_file_path =
79
case @aligned_config_file do
@@ -66,6 +68,23 @@ defmodule AlignedProofAggregationService do
6668
end
6769
end
6870

71+
# From a given aggregated proof event, it fetches the transaction
72+
# and returns the aggregator (:sp1, :risc0) based on the function signature
73+
def get_aggregator!(agg_proof) do
74+
tx_hash = agg_proof.tx_hash
75+
{:ok, tx} = Explorer.EthClient.get_transaction_by_hash(tx_hash)
76+
input = Map.get(tx, "input")
77+
# In solidity, the function signatures are the first 4 bytes of the input
78+
# Note: first two characters are the 0x
79+
function_signature = String.slice(input, 0..9)
80+
81+
case function_signature do
82+
@verifyRisc0_solidity_signature -> :risc0
83+
@verifySp1_solidity_signature -> :sp1
84+
_ -> nil
85+
end
86+
end
87+
6988
def get_block_timestamp(block_number) do
7089
case Ethers.Utils.get_block_timestamp(block_number) do
7190
{:ok, timestamp} -> DateTime.from_unix!(timestamp)

explorer/lib/explorer/eth_client.ex

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ defmodule Explorer.EthClient do
66
eth_send("eth_getBlockByNumber", [block_number, false])
77
end
88

9+
def get_transaction_by_hash(tx_hash) do
10+
eth_send("eth_getTransactionByHash", [tx_hash])
11+
end
12+
913
defp eth_send(method, params, id \\ 1) do
1014
headers = [{"Content-Type", "application/json"}]
1115
body = Jason.encode!(%{jsonrpc: "2.0", method: method, params: params, id: id})
@@ -15,9 +19,14 @@ defmodule Explorer.EthClient do
1519
case response do
1620
{:ok, %Finch.Response{status: 200, body: body}} ->
1721
case Jason.decode(body) do
18-
{:ok, %{error: error} = _} -> {:error, error.message}
19-
{:ok, body} -> {:ok, Map.get(body, "result")}
20-
{:error, _} -> {:error, :invalid_json}
22+
{:ok, %{"error" => %{"message" => message}}} ->
23+
{:error, message}
24+
25+
{:ok, body} ->
26+
{:ok, Map.get(body, "result")}
27+
28+
{:error, _} ->
29+
{:error, :invalid_json}
2130
end
2231

2332
{:ok, %Finch.Response{status: status}} ->

explorer/lib/explorer/models/aggregated_proofs.ex

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ defmodule AggregatedProofs do
1212
field(:block_timestamp, :utc_datetime)
1313
field(:tx_hash, :string)
1414
field(:number_of_proofs, :integer)
15+
field(:aggregator, Ecto.Enum, values: [:sp1, :risc0])
1516

1617
has_many(:proofs_agg_mode, AggregationModeProof,
1718
foreign_key: :agg_proof_id,
@@ -33,7 +34,8 @@ defmodule AggregatedProofs do
3334
:block_number,
3435
:block_timestamp,
3536
:tx_hash,
36-
:number_of_proofs
37+
:number_of_proofs,
38+
:aggregator
3739
])
3840
|> validate_required([
3941
:merkle_root,

explorer/lib/explorer/periodically.ex

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,11 @@ defmodule Explorer.Periodically do
113113
proofs
114114
|> Enum.zip(proof_hashes)
115115
|> Enum.map(fn {agg_proof, hashes} ->
116+
aggregator = AlignedProofAggregationService.get_aggregator!(agg_proof)
117+
116118
agg_proof =
117119
agg_proof
120+
|> Map.merge(%{aggregator: aggregator})
118121
|> Map.merge(%{number_of_proofs: length(hashes)})
119122

120123
{:ok, %{id: id}} = AggregatedProofs.insert_or_update(agg_proof)

explorer/lib/explorer_web/components/agg_proofs_table.ex

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,34 @@ defmodule ExplorerWeb.AggProofsTable do
4444
<:col :let={proof} label="Number of proofs">
4545
<%= proof.number_of_proofs |> Helpers.format_number() %>
4646
</:col>
47+
48+
<:col :let={proof} label="Aggregator">
49+
<%= case proof.aggregator do %>
50+
<% :sp1 -> %>
51+
<.sp1_badge />
52+
<% :risc0 -> %>
53+
<.risc0_badge />
54+
<% _ -> %>
55+
<span>Unknown</span>
56+
<% end %>
57+
</:col>
4758
</.table>
4859
"""
4960
end
61+
62+
defp sp1_badge(assigns) do
63+
~H"""
64+
<div class="rounded-full p-1 px-5 border w-fit" style="border-color: #FE11C5">
65+
<p style="color: #FE11C5">SP1</p>
66+
</div>
67+
"""
68+
end
69+
70+
defp risc0_badge(assigns) do
71+
~H"""
72+
<div class="rounded-full p-1 px-5 w-fit" style="background-color: #FEFF9D">
73+
<p class="text-black">RISC0</p>
74+
</div>
75+
"""
76+
end
5077
end

0 commit comments

Comments
 (0)