Skip to content

Commit

Permalink
Merge branch 'main' into chore/add-wormchain-ibc-receiver-rust-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
kakucodes authored Oct 18, 2024
2 parents 078742f + e82db71 commit 1f2f620
Show file tree
Hide file tree
Showing 38 changed files with 2,270 additions and 1,816 deletions.
21 changes: 10 additions & 11 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,21 @@ As these 3rd party audits are completed and issues are sufficiently addressed, w
- **[April 2023 - Trail of Bits](https://github.com/wormhole-foundation/wormhole-audits/blob/main/Wormhole_Audit_Report_TrailOfBits_2023-04.pdf)**: _Guardian node: Governor and Watchers_
- **[April 2023 - OtterSec](https://github.com/wormhole-foundation/wormhole-audits/blob/main/Wormhole_OtterSec_Sui_2023-04.pdf)**: _Sui Contracts_
- **[May 2023 - Runtime Verification](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2023-05_Runtime_Verification_Wormhole_EVM.pdf)**: _Formal Verification of EVM contracts_
- **[Jan 2024 - Cyfrin](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-01-10-cyfrin-thermae-v2.0.pdf)**: _Uniswap Liquidity Layer EVM Contracts_
- **[Jan 2024 - OtterSec](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-01-ottersec-terra.pdf)**: _Terra Classic Contract Upgrades_
- **[Feb 2024 - Cyfrin](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-04-09-cyfrin-wormhole-evm-cctp-v2-1.pdf)**: _CCTP EVM Contracts_
- **[Mar 2024 - Cyfrin](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-04-11-cyfrin-wormhole-evm-ntt.pdf)**: _NTT EVM Contracts_
- **[Mar 2024 - Cantina](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-04-cantina-wormhole-evm-ntt.pdf)**: _NTT EVM Contracts_
- **[Mar 2024 - OtterSec](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-03-28-ottersec-solana-ntt.pdf)**: _NTT Solana Contracts_
- **[Mar 2024 - Neodyme](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-04-12-neodyme-solana-ntt.pdf)**: _NTT Solana Contracts_
- **[January 2024 - Cyfrin](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-01-10-cyfrin-thermae-v2.0.pdf)**: _Uniswap Liquidity Layer EVM Contracts_
- **[January 2024 - OtterSec](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-01-ottersec-terra.pdf)**: _Terra Classic Contract Upgrades_
- **[February 2024 - Cyfrin](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-04-09-cyfrin-wormhole-evm-cctp-v2-1.pdf)**: _CCTP EVM Contracts_
- **[March 2024 - Cyfrin](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-04-11-cyfrin-wormhole-evm-ntt.pdf)**: _NTT EVM Contracts_
- **[March 2024 - Cantina](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-04-cantina-wormhole-evm-ntt.pdf)**: _NTT EVM Contracts_
- **[March 2024 - OtterSec](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-03-28-ottersec-solana-ntt.pdf)**: _NTT Solana Contracts_
- **[March 2024 - Neodyme](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-04-12-neodyme-solana-ntt.pdf)**: _NTT Solana Contracts_
- **[July 2024 - Cyfrin](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-07-23-cyfrin-wormhole-evm-ntt-diff-v1.1.0.pdf)**: _NTT EVM v1.1.0_
- **[August 2024 - OtterSec](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-08-02-ottersec-solana-ntt-token-extensions.pdf)**: _NTT Solana Token Extensions_

## Bug Bounty Program

The Wormhole project operates a bug bounty program to financially incentivize independent researchers for finding and responsibly disclosing security issues.

- [Immunefi-Hosted Program](https://immunefi.com/bounty/wormhole/)
- **Scopes**: Guardian and Smart Contracts
- **Rewards**: Up to $5,000,000 USDC
- **KYC**: Required
[Immunefi-Hosted Program](https://immunefi.com/bug-bounty/wormhole/information/)

If you find a security issue in Wormhole, please report the issue immediately using the bug bounty program above.

Expand Down
2 changes: 2 additions & 0 deletions cspell-custom-words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ unbond
Uncompromised
undercollateralization
unforgeable
unichain
Unichain
unnormalize
untampered
utest
Expand Down
21 changes: 21 additions & 0 deletions ethereum/env/.env.unichain.testnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Unichain testnet env
# Rename to .env

# Common config for forge deployment
RPC_URL=fill_this_in
FORGE_ARGS="--legacy"

# Wormhole Core Migrations
INIT_SIGNERS=["0x13947Bd48b18E53fdAeEe77F3473391aC727C638"]
INIT_CHAIN_ID=44
INIT_GOV_CHAIN_ID=0x1
INIT_GOV_CONTRACT=0x0000000000000000000000000000000000000000000000000000000000000004
INIT_EVM_CHAIN_ID=1301

# Bridge Migrations
BRIDGE_INIT_CHAIN_ID=44
BRIDGE_INIT_GOV_CHAIN_ID=0x1
BRIDGE_INIT_GOV_CONTRACT=0x0000000000000000000000000000000000000000000000000000000000000004
BRIDGE_INIT_FINALITY=1
# Unichain is an OP Stack chain so *probably* has the same WETH address. Should verify this! https://docs.optimism.io/stack/protocol/features/custom-gas-token#what-is-the-wrapped-erc-20-gas-token
BRIDGE_INIT_WETH=0x4200000000000000000000000000000000000006
15 changes: 9 additions & 6 deletions node/cmd/guardiand/adminclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
"github.com/spf13/pflag"
"golang.org/x/crypto/sha3"

"github.com/certusone/wormhole/node/pkg/common"
"github.com/certusone/wormhole/node/pkg/guardiansigner"
gossipv1 "github.com/certusone/wormhole/node/pkg/proto/gossip/v1"
publicrpcv1 "github.com/certusone/wormhole/node/pkg/proto/publicrpc/v1"
"github.com/wormhole-foundation/wormhole/sdk"
Expand Down Expand Up @@ -102,7 +102,7 @@ var AdminCmd = &cobra.Command{
}

var AdminClientSignWormchainAddress = &cobra.Command{
Use: "sign-wormchain-address [/path/to/guardianKey] [wormchain-validator-address]",
Use: "sign-wormchain-address [vaa-signer-uri] [wormchain-validator-address]",
Short: "Sign a wormchain validator address. Only sign the address that you control the key for and will be for your validator.",
RunE: runSignWormchainValidatorAddress,
Args: cobra.ExactArgs(2),
Expand Down Expand Up @@ -236,22 +236,25 @@ func getPublicRPCServiceClient(ctx context.Context, addr string) (*grpc.ClientCo
}

func runSignWormchainValidatorAddress(cmd *cobra.Command, args []string) error {
guardianKeyPath := args[0]
guardianSignerUri := args[0]
wormchainAddress := args[1]
if !strings.HasPrefix(wormchainAddress, "wormhole") || strings.HasPrefix(wormchainAddress, "wormholeval") {
return errors.New("must provide a bech32 address that has 'wormhole' prefix")
}
gk, err := common.LoadGuardianKey(guardianKeyPath, *unsafeDevnetMode)

guardianSigner, err := guardiansigner.NewGuardianSignerFromUri(guardianSignerUri, *unsafeDevnetMode)
if err != nil {
return fmt.Errorf("failed to load guardian key: %w", err)
return fmt.Errorf("failed to create new guardian signer from uri: %w", err)
}

addr, err := types.GetFromBech32(wormchainAddress, "wormhole")
if err != nil {
return fmt.Errorf("failed to decode wormchain address: %w", err)
}

// Hash and sign address
addrHash := crypto.Keccak256Hash(sdk.SignedWormchainAddressPrefix, addr)
sig, err := crypto.Sign(addrHash[:], gk)
sig, err := guardianSigner.Sign(addrHash.Bytes())
if err != nil {
return fmt.Errorf("failed to sign wormchain address: %w", err)
}
Expand Down
1 change: 1 addition & 0 deletions node/cmd/guardiand/adminnodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ func runListNodes(cmd *cobra.Command, args []string) {
{"Linea", vaa.ChainIDLinea},
{"Berachain", vaa.ChainIDBerachain},
{"Snaxchain", vaa.ChainIDSnaxchain},
{"Unichain", vaa.ChainIDUnichain},
{"Wormchain", vaa.ChainIDWormchain},
{"Sepolia", vaa.ChainIDSepolia},
{"Holesky", vaa.ChainIDHolesky},
Expand Down
69 changes: 55 additions & 14 deletions node/cmd/guardiand/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"syscall"
"time"

"github.com/certusone/wormhole/node/pkg/guardiansigner"
"github.com/certusone/wormhole/node/pkg/watchers"
"github.com/certusone/wormhole/node/pkg/watchers/ibc"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
Expand Down Expand Up @@ -62,8 +63,9 @@ var (

statusAddr *string

guardianKeyPath *string
solanaContract *string
guardianKeyPath *string
guardianSignerUri *string
solanaContract *string

ethRPC *string
ethContract *string
Expand Down Expand Up @@ -187,6 +189,9 @@ var (
snaxchainRPC *string
snaxchainContract *string

unichainRPC *string
unichainContract *string

sepoliaRPC *string
sepoliaContract *string

Expand Down Expand Up @@ -266,7 +271,8 @@ func init() {

dataDir = NodeCmd.Flags().String("dataDir", "", "Data directory")

guardianKeyPath = NodeCmd.Flags().String("guardianKey", "", "Path to guardian key (required)")
guardianKeyPath = NodeCmd.Flags().String("guardianKey", "", "Path to guardian key")
guardianSignerUri = NodeCmd.Flags().String("guardianSignerUri", "", "Guardian signer URI")
solanaContract = NodeCmd.Flags().String("solanaContract", "", "Address of the Solana program (required)")

ethRPC = node.RegisterFlagWithValidationOrFail(NodeCmd, "ethRPC", "Ethereum RPC URL", "ws://eth-devnet:8545", []string{"ws", "wss"})
Expand Down Expand Up @@ -394,6 +400,9 @@ func init() {
snaxchainRPC = node.RegisterFlagWithValidationOrFail(NodeCmd, "snaxchainRPC", "Snaxchain RPC URL", "ws://eth-devnet:8545", []string{"ws", "wss"})
snaxchainContract = NodeCmd.Flags().String("snaxchainContract", "", "Snaxchain contract address")

unichainRPC = node.RegisterFlagWithValidationOrFail(NodeCmd, "unichainRPC", "Unichain RPC URL", "ws://eth-devnet:8545", []string{"ws", "wss"})
unichainContract = NodeCmd.Flags().String("unichainContract", "", "Unichain contract address")

baseRPC = node.RegisterFlagWithValidationOrFail(NodeCmd, "baseRPC", "Base RPC URL", "ws://eth-devnet:8545", []string{"ws", "wss"})
baseContract = NodeCmd.Flags().String("baseContract", "", "Base contract address")

Expand Down Expand Up @@ -622,7 +631,22 @@ func runNode(cmd *cobra.Command, args []string) {
logger.Fatal("Please specify --nodeKey")
}
if *guardianKeyPath == "" {
logger.Fatal("Please specify --guardianKey")
// This if-statement is nested, since checking if both are empty at once will always result in the else-branch
// being executed if at least one is specified. For example, in the case where the signer URI is specified and
// the guardianKeyPath not, then the else-statement will create an empty `file://` URI.
if *guardianSignerUri == "" {
logger.Fatal("Please specify --guardianKey or --guardianSignerUri")
}
} else {
// To avoid confusion, require that only guardianKey or guardianSignerUri can be specified
if *guardianSignerUri != "" {
logger.Fatal("Please only specify --guardianKey or --guardianSignerUri")
}

// If guardianKeyPath is set, set guardianSignerUri to the file signer URI, pointing to guardianKeyPath.
// This ensures that the signer-abstracted guardian has backwards compatibility with guardians that would
// just like to ignore the new guardianSignerUri altogether.
*guardianSignerUri = fmt.Sprintf("file://%s", *guardianKeyPath)
}
if *adminSocketPath == "" {
logger.Fatal("Please specify --adminSocket")
Expand All @@ -644,20 +668,23 @@ func runNode(cmd *cobra.Command, args []string) {

// In devnet mode, we generate a deterministic guardian key and write it to disk.
if env == common.UnsafeDevNet {
err := devnet.GenerateAndStoreDevnetGuardianKey(*guardianKeyPath)
if err != nil {
logger.Fatal("failed to generate devnet guardian key", zap.Error(err))
// Only if the signer is file-based should we generate the deterministic key and write it to disk
if st, _, _ := guardiansigner.ParseSignerUri(*guardianSignerUri); st == guardiansigner.FileSignerType {
err := devnet.GenerateAndStoreDevnetGuardianKey(*guardianKeyPath)
if err != nil {
logger.Fatal("failed to generate devnet guardian key", zap.Error(err))
}
}
}

// Load guardian key
gk, err := common.LoadGuardianKey(*guardianKeyPath, env == common.UnsafeDevNet)
// Create the Guardian Signer
guardianSigner, err := guardiansigner.NewGuardianSignerFromUri(*guardianSignerUri, env == common.UnsafeDevNet)
if err != nil {
logger.Fatal("failed to load guardian key", zap.Error(err))
logger.Fatal("failed to create a new guardian signer", zap.Error(err))
}

logger.Info("Loaded guardian key", zap.String(
"address", ethcrypto.PubkeyToAddress(gk.PublicKey).String()))
"address", ethcrypto.PubkeyToAddress(guardianSigner.PublicKey()).String()))

// Load p2p private key
var p2pKey libp2p_crypto.PrivKey
Expand Down Expand Up @@ -713,7 +740,7 @@ func runNode(cmd *cobra.Command, args []string) {
labels := map[string]string{
"node_name": *nodeName,
"node_key": peerID.String(),
"guardian_addr": ethcrypto.PubkeyToAddress(gk.PublicKey).String(),
"guardian_addr": ethcrypto.PubkeyToAddress(guardianSigner.PublicKey()).String(),
"network": *p2pNetworkID,
"version": version.Version(),
}
Expand Down Expand Up @@ -758,6 +785,7 @@ func runNode(cmd *cobra.Command, args []string) {
*lineaContract = checkEvmArgs(logger, *lineaRPC, *lineaContract, "linea", true)
*berachainContract = checkEvmArgs(logger, *berachainRPC, *berachainContract, "berachain", false)
*snaxchainContract = checkEvmArgs(logger, *snaxchainRPC, *snaxchainContract, "snaxchain", true)
*unichainContract = checkEvmArgs(logger, *unichainRPC, *unichainContract, "unichain", false)

// These chains will only ever be testnet / devnet.
*sepoliaContract = checkEvmArgs(logger, *sepoliaRPC, *sepoliaContract, "sepolia", false)
Expand Down Expand Up @@ -901,6 +929,7 @@ func runNode(cmd *cobra.Command, args []string) {
rpcMap["terraLCD"] = *terraLCD
rpcMap["terra2WS"] = *terra2WS
rpcMap["terra2LCD"] = *terra2LCD
rpcMap["unichainRPC"] = *unichainRPC
rpcMap["gatewayWS"] = *gatewayWS
rpcMap["gatewayLCD"] = *gatewayLCD
rpcMap["wormchainURL"] = *wormchainURL
Expand Down Expand Up @@ -1052,7 +1081,7 @@ func runNode(cmd *cobra.Command, args []string) {
info.PromRemoteURL = *promRemoteURL
info.Labels = map[string]string{
"node_name": *nodeName,
"guardian_addr": ethcrypto.PubkeyToAddress(gk.PublicKey).String(),
"guardian_addr": ethcrypto.PubkeyToAddress(guardianSigner.PublicKey()).String(),
"network": *p2pNetworkID,
"version": version.Version(),
"product": "wormhole",
Expand Down Expand Up @@ -1334,6 +1363,18 @@ func runNode(cmd *cobra.Command, args []string) {
watcherConfigs = append(watcherConfigs, wc)
}

if shouldStart(unichainRPC) {
wc := &evm.WatcherConfig{
NetworkID: "unichain",
ChainID: vaa.ChainIDUnichain,
Rpc: *unichainRPC,
Contract: *unichainContract,
CcqBackfillCache: *ccqBackfillCache,
}

watcherConfigs = append(watcherConfigs, wc)
}

if shouldStart(terraWS) {
wc := &cosmwasm.WatcherConfig{
NetworkID: "terra",
Expand Down Expand Up @@ -1565,7 +1606,7 @@ func runNode(cmd *cobra.Command, args []string) {

guardianNode := node.NewGuardianNode(
env,
gk,
guardianSigner,
)

guardianOptions := []*node.GuardianOption{
Expand Down
Loading

0 comments on commit 1f2f620

Please sign in to comment.