Skip to content

Commit fb5b450

Browse files
authored
Tee precompile and preinstall upgrade handler (#31)
* init updates * cleanup * test script * updates * updates
1 parent 8d35b76 commit fb5b450

6 files changed

Lines changed: 761 additions & 29 deletions

File tree

contrib/images/evmd-env/Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,17 @@ WORKDIR /evmd
3131
COPY contrib/images/evmd-env/wrapper.sh /usr/bin/wrapper.sh
3232
COPY test_deployment.sh /usr/bin/test_deployment.sh
3333
COPY multi_node_startup.sh /usr/bin/multi_node_startup.sh
34+
COPY scripts/create_software_upgrade_proposal.sh /usr/bin/create_software_upgrade_proposal.sh
3435
COPY --from=evmd-builder /work/build/evmd /evmd/
3536
COPY --from=evmd-builder /work/build/evmd /usr/local/bin/
3637

3738
# Set proper ownership and permissions before switching to nonroot user
3839
RUN chown nonroot:nonroot /usr/bin/wrapper.sh && chmod +x /usr/bin/wrapper.sh
3940
RUN chown nonroot:nonroot /usr/bin/test_deployment.sh && chmod +x /usr/bin/test_deployment.sh
4041
RUN chown nonroot:nonroot /usr/bin/multi_node_startup.sh && chmod +x /usr/bin/multi_node_startup.sh
42+
RUN chown nonroot:nonroot /usr/bin/create_software_upgrade_proposal.sh && chmod +x /usr/bin/create_software_upgrade_proposal.sh
4143
RUN chown -R nonroot:nonroot /evmd
4244

4345
USER nonroot
4446

45-
ENTRYPOINT ["/usr/bin/multi_node_startup.sh"]
47+
ENTRYPOINT ["/usr/bin/multi_node_startup.sh"]

evmd/upgrades.go

Lines changed: 88 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ package evmd
22

33
import (
44
"context"
5+
"fmt"
6+
"slices"
57

6-
"github.com/cosmos/evm/x/vm/types"
8+
vmtypes "github.com/cosmos/evm/x/vm/types"
9+
"github.com/ethereum/go-ethereum/common"
710

811
storetypes "cosmossdk.io/store/types"
912
upgradetypes "cosmossdk.io/x/upgrade/types"
@@ -13,17 +16,24 @@ import (
1316
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
1417
)
1518

16-
// UpgradeName defines the on-chain upgrade name for the sample EVMD upgrade
17-
// from v0.5.0 to v0.6.0.
18-
//
19-
// NOTE: This upgrade defines a reference implementation of what an upgrade
20-
// could look like when an application is migrating from EVMD version
21-
// v0.4.0 to v0.5.x
22-
const UpgradeName = "v0.5.0-to-v0.6.0"
19+
const (
20+
// LegacyUpgradeName is kept to preserve compatibility with already-published
21+
// upgrade proposal names from earlier deployments.
22+
LegacyUpgradeName = "v0.5.0-to-v0.6.0"
23+
24+
// UpgradeName defines the on-chain upgrade name for enabling missing EVM
25+
// preinstalls on an already-running network and optionally activating the
26+
// latest static precompile.
27+
UpgradeName = "v0.6.0-enable-missing-preinstalls"
28+
29+
// OptionalStaticPrecompileAddress is enabled during the upgrade if missing.
30+
OptionalStaticPrecompileAddress = vmtypes.TEEPrecompileAddress
31+
)
2332

2433
func (app EVMD) RegisterUpgradeHandlers() {
34+
// Legacy sample upgrade (kept intact for compatibility with existing plans).
2535
app.UpgradeKeeper.SetUpgradeHandler(
26-
UpgradeName,
36+
LegacyUpgradeName,
2737
func(ctx context.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
2838
sdkCtx := sdk.UnwrapSDKContext(ctx)
2939
sdkCtx.Logger().Debug("this is a debug level message to test that verbose logging mode has properly been enabled during a chain upgrade")
@@ -53,16 +63,77 @@ func (app EVMD) RegisterUpgradeHandlers() {
5363
// (Required for NON-18 denom chains *only)
5464
// Update EVM params to add Extended denom options
5565
// Ensure that this corresponds to the EVM denom
56-
// (tyically the bond denom)
66+
// (typically the bond denom)
5767
evmParams := app.EVMKeeper.GetParams(sdkCtx)
58-
evmParams.ExtendedDenomOptions = &types.ExtendedDenomOptions{ExtendedDenom: "atest"}
59-
err := app.EVMKeeper.SetParams(sdkCtx, evmParams)
60-
if err != nil {
68+
evmParams.ExtendedDenomOptions = &vmtypes.ExtendedDenomOptions{ExtendedDenom: "atest"}
69+
if err := app.EVMKeeper.SetParams(sdkCtx, evmParams); err != nil {
70+
return nil, err
71+
}
72+
73+
// Initialize EvmCoinInfo in the module store. Chains bootstrapped before
74+
// v0.5.0 binaries never stored this information (it lived only in process
75+
// globals), so migrating nodes would otherwise see an empty EvmCoinInfo on
76+
// upgrade.
77+
if err := app.EVMKeeper.InitEvmCoinInfo(sdkCtx); err != nil {
6178
return nil, err
6279
}
63-
// Initialize EvmCoinInfo in the module store. Chains bootstrapped before v0.5.0
64-
// binaries never stored this information (it lived only in process globals),
65-
// so migrating nodes would otherwise see an empty EvmCoinInfo on upgrade.
80+
81+
return app.ModuleManager.RunMigrations(ctx, app.Configurator(), fromVM)
82+
},
83+
)
84+
85+
// New upgrade to backfill preinstalls and optionally activate new static precompile.
86+
app.UpgradeKeeper.SetUpgradeHandler(
87+
UpgradeName,
88+
func(ctx context.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
89+
sdkCtx := sdk.UnwrapSDKContext(ctx)
90+
91+
// Optionally activate a new static precompile if it is available in
92+
// the binary and not yet active in chain state.
93+
evmParams := app.EVMKeeper.GetParams(sdkCtx)
94+
if !slices.Contains(evmParams.ActiveStaticPrecompiles, OptionalStaticPrecompileAddress) {
95+
if !slices.Contains(vmtypes.AvailableStaticPrecompiles, OptionalStaticPrecompileAddress) {
96+
return nil, fmt.Errorf("cannot activate static precompile %s: address not available in binary", OptionalStaticPrecompileAddress)
97+
}
98+
evmParams.ActiveStaticPrecompiles = append(evmParams.ActiveStaticPrecompiles, OptionalStaticPrecompileAddress)
99+
if err := app.EVMKeeper.SetParams(sdkCtx, evmParams); err != nil {
100+
return nil, err
101+
}
102+
}
103+
104+
// Add only missing default preinstalls. If an address has no code hash
105+
// but already has an account, abort to avoid mutating unknown state.
106+
missingPreinstalls := make([]vmtypes.Preinstall, 0, len(vmtypes.DefaultPreinstalls))
107+
for _, preinstall := range vmtypes.DefaultPreinstalls {
108+
addr := common.HexToAddress(preinstall.Address)
109+
codeHash := app.EVMKeeper.GetCodeHash(sdkCtx, addr)
110+
if !vmtypes.IsEmptyCodeHash(codeHash.Bytes()) {
111+
continue
112+
}
113+
114+
accAddress := sdk.AccAddress(addr.Bytes())
115+
if acc := app.AccountKeeper.GetAccount(sdkCtx, accAddress); acc != nil {
116+
// Skip addresses that already have an account (e.g. a funded EOA)
117+
// rather than halting the chain
118+
sdkCtx.Logger().Warn(
119+
"skipping preinstall: account exists with empty code hash",
120+
"address", preinstall.Address,
121+
)
122+
continue
123+
}
124+
125+
missingPreinstalls = append(missingPreinstalls, preinstall)
126+
}
127+
128+
if len(missingPreinstalls) > 0 {
129+
if err := app.EVMKeeper.AddPreinstalls(sdkCtx, missingPreinstalls); err != nil {
130+
return nil, err
131+
}
132+
}
133+
134+
// Ensure EvmCoinInfo is present in the module store. This is idempotent
135+
// and required because this upgrade path may run on chains that never
136+
// executed the LegacyUpgradeName handler (which also calls this).
66137
if err := app.EVMKeeper.InitEvmCoinInfo(sdkCtx); err != nil {
67138
return nil, err
68139
}
@@ -75,7 +146,7 @@ func (app EVMD) RegisterUpgradeHandlers() {
75146
panic(err)
76147
}
77148

78-
if upgradeInfo.Name == UpgradeName && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) {
149+
if (upgradeInfo.Name == LegacyUpgradeName || upgradeInfo.Name == UpgradeName) && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) {
79150
storeUpgrades := storetypes.StoreUpgrades{
80151
Added: []string{},
81152
}

multi_node_startup.sh

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ KEYRING="test"
66
KEYALGO="eth_secp256k1"
77
LOGLEVEL="info"
88
BASEFEE=10000000
9-
109
BASEDIR="${BASEDIR:-"$HOME/.og-evm-devnet"}"
1110

1211
NODE_NUMBER="${NODE_NUMBER:-}"
@@ -364,14 +363,17 @@ start_validator() {
364363
echo "JSON-RPC: $JSONRPC_PORT"
365364
echo "=========================================="
366365

367-
evmd start \
368-
--pruning nothing \
369-
--log_level "$LOGLEVEL" \
370-
--minimum-gas-prices=0ogwei \
371-
--evm.min-tip=0 \
372-
--home "$HOME_DIR" \
373-
--json-rpc.api eth,txpool,personal,net,debug,web3 \
366+
START_ARGS=(
367+
--pruning nothing
368+
--log_level "$LOGLEVEL"
369+
--minimum-gas-prices=0ogwei
370+
--evm.min-tip=0
371+
--home "$HOME_DIR"
372+
--json-rpc.api eth,txpool,personal,net,debug,web3
374373
--chain-id "$CHAINID"
374+
)
375+
376+
exec evmd start "${START_ARGS[@]}"
375377
}
376378

377379
if [[ "$GENERATE_GENESIS" == "true" ]]; then
@@ -392,4 +394,4 @@ if [[ "$GENERATE_GENESIS" != "true" && "$START_VALIDATOR" != "true" ]]; then
392394
echo " START_VALIDATOR=true NODE_NUMBER=0 $0"
393395
echo ""
394396
usage
395-
fi
397+
fi

precompiles/types/static_precompiles.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,12 +189,10 @@ func (s StaticPrecompiles) WithSlashingPrecompile(
189189
}
190190

191191
func (s StaticPrecompiles) WithTEEPrecompile() StaticPrecompiles {
192-
fmt.Println("=== REGISTERING TEE PRECOMPILE ===")
193192
teePrecompile, err := teeprecompile.NewPrecompile()
194193
if err != nil {
195194
panic(fmt.Errorf("failed to instantiate TEE precompile: %w", err))
196195
}
197-
fmt.Printf("TEE Address: %s\n", teePrecompile.Address().Hex())
198196
s[teePrecompile.Address()] = teePrecompile
199197
return s
200198
}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
usage() {
6+
cat <<'EOF'
7+
Create a governance software-upgrade proposal JSON, and optionally submit it.
8+
9+
Usage:
10+
create_software_upgrade_proposal.sh [options]
11+
12+
Required:
13+
--upgrade-name NAME Upgrade plan name (must match UpgradeName in app binary)
14+
--upgrade-height HEIGHT Upgrade height
15+
--from KEY_OR_ADDRESS Key name/address used to submit the proposal
16+
17+
Optional:
18+
--chain-id ID Chain ID (default: env CHAIN_ID or 10740)
19+
--node NODE RPC node (default: env NODE or tcp://127.0.0.1:26657)
20+
--home PATH Node home for keyring/query (default: env HOME_DIR or ~/.og-evm-devnet/val0)
21+
--keyring-backend BACKEND Keyring backend (default: env KEYRING_BACKEND or test)
22+
--authority ADDRESS Gov module authority address (auto-queried if omitted)
23+
--title TEXT Proposal title (default: "Software Upgrade: <name>")
24+
--summary TEXT Proposal summary
25+
--metadata URI Proposal metadata URI (default: ipfs://CID)
26+
--deposit COIN Deposit (default: 10000000ogwei)
27+
--fees COIN Tx fees when submitting (default: 2000000000000ogwei)
28+
--proposal-file PATH Output proposal JSON path
29+
--submit Submit proposal tx after generating JSON
30+
-h, --help Show this help
31+
EOF
32+
}
33+
34+
CHAIN_ID="${CHAIN_ID:-10740}"
35+
NODE="${NODE:-tcp://127.0.0.1:26657}"
36+
HOME_DIR="${HOME_DIR:-$HOME/.og-evm-devnet/val0}"
37+
KEYRING_BACKEND="${KEYRING_BACKEND:-test}"
38+
39+
UPGRADE_NAME=""
40+
UPGRADE_HEIGHT=""
41+
FROM=""
42+
AUTHORITY=""
43+
TITLE=""
44+
SUMMARY="Enable missing preinstalls and optional static precompile activation"
45+
METADATA="ipfs://CID"
46+
DEPOSIT="10000000ogwei"
47+
FEES="2000000000000ogwei"
48+
SUBMIT=false
49+
PROPOSAL_FILE=""
50+
51+
while [[ $# -gt 0 ]]; do
52+
case "$1" in
53+
--upgrade-name) UPGRADE_NAME="$2"; shift 2 ;;
54+
--upgrade-height) UPGRADE_HEIGHT="$2"; shift 2 ;;
55+
--from) FROM="$2"; shift 2 ;;
56+
--chain-id) CHAIN_ID="$2"; shift 2 ;;
57+
--node) NODE="$2"; shift 2 ;;
58+
--home) HOME_DIR="$2"; shift 2 ;;
59+
--keyring-backend) KEYRING_BACKEND="$2"; shift 2 ;;
60+
--authority) AUTHORITY="$2"; shift 2 ;;
61+
--title) TITLE="$2"; shift 2 ;;
62+
--summary) SUMMARY="$2"; shift 2 ;;
63+
--metadata) METADATA="$2"; shift 2 ;;
64+
--deposit) DEPOSIT="$2"; shift 2 ;;
65+
--fees) FEES="$2"; shift 2 ;;
66+
--proposal-file) PROPOSAL_FILE="$2"; shift 2 ;;
67+
--submit) SUBMIT=true; shift ;;
68+
-h|--help) usage; exit 0 ;;
69+
*) echo "Unknown option: $1"; usage; exit 1 ;;
70+
esac
71+
done
72+
73+
if [[ -z "$UPGRADE_NAME" || -z "$UPGRADE_HEIGHT" || -z "$FROM" ]]; then
74+
echo "Error: --upgrade-name, --upgrade-height, and --from are required."
75+
usage
76+
exit 1
77+
fi
78+
79+
if [[ -z "$TITLE" ]]; then
80+
TITLE="Software Upgrade: $UPGRADE_NAME"
81+
fi
82+
83+
if [[ -z "$PROPOSAL_FILE" ]]; then
84+
PROPOSAL_FILE="/tmp/software-upgrade-${UPGRADE_NAME}-${UPGRADE_HEIGHT}.json"
85+
fi
86+
87+
if [[ -z "$AUTHORITY" ]]; then
88+
command -v jq >/dev/null 2>&1 || { echo "Error: jq is required to auto-detect --authority."; exit 1; }
89+
AUTHORITY_JSON="$(evmd query auth module-account gov --node "$NODE" --home "$HOME_DIR" -o json)"
90+
AUTHORITY="$(echo "$AUTHORITY_JSON" | jq -r '.account.base_account.address // .account.value.address // empty')"
91+
if [[ -z "$AUTHORITY" ]]; then
92+
echo "Error: unable to determine gov authority address. Pass --authority explicitly."
93+
exit 1
94+
fi
95+
fi
96+
97+
mkdir -p "$(dirname "$PROPOSAL_FILE")"
98+
99+
cat >"$PROPOSAL_FILE" <<EOF
100+
{
101+
"messages": [
102+
{
103+
"@type": "/cosmos.upgrade.v1beta1.MsgSoftwareUpgrade",
104+
"authority": "$AUTHORITY",
105+
"plan": {
106+
"name": "$UPGRADE_NAME",
107+
"height": "$UPGRADE_HEIGHT"
108+
}
109+
}
110+
],
111+
"metadata": "$METADATA",
112+
"deposit": "$DEPOSIT",
113+
"title": "$TITLE",
114+
"summary": "$SUMMARY"
115+
}
116+
EOF
117+
118+
echo "Wrote proposal file: $PROPOSAL_FILE"
119+
echo "Upgrade Name: $UPGRADE_NAME"
120+
echo "Upgrade Height: $UPGRADE_HEIGHT"
121+
echo "Gov Authority: $AUTHORITY"
122+
echo "Deposit: $DEPOSIT"
123+
124+
if [[ "$SUBMIT" == "true" ]]; then
125+
echo "Submitting proposal..."
126+
evmd tx gov submit-proposal "$PROPOSAL_FILE" \
127+
--from "$FROM" \
128+
--home "$HOME_DIR" \
129+
--keyring-backend "$KEYRING_BACKEND" \
130+
--chain-id "$CHAIN_ID" \
131+
--node "$NODE" \
132+
--fees "$FEES" \
133+
-y
134+
else
135+
echo ""
136+
echo "Submit command:"
137+
echo " evmd tx gov submit-proposal \"$PROPOSAL_FILE\" --from \"$FROM\" --home \"$HOME_DIR\" --keyring-backend \"$KEYRING_BACKEND\" --chain-id \"$CHAIN_ID\" --node \"$NODE\" --fees \"$FEES\" -y"
138+
fi

0 commit comments

Comments
 (0)