馃摉 Private Key Management of CreateX
Deployer 路 pcaversaccio/createx 路 Discussion #61 (original) (raw)
For the track record, I converted this issue from @radeksvarz into this discussion thread and I also pinned it to the discussion tab.
@radeksvarz thanks for asking these important questions. I will try to address them in the most transparent way:
- Question 1: Risk of losing the private key of the
CreateX
deployer account0xeD456e05CaAb11d66C4c797dD6c1D6f9A7F352b5
.- Answer: Me and @mds1 each have a copy of the private key to be a backup for each other. We keep the private key very secure, but there is always the risk that we could both lose the private key together one day. I can't go into detail about how we store it (for obvious reasons), but I can assure you that I keep several copies myself in safe places. So what exactly is the risk for this scenario: Assuming we have lost the private key, but not leaked in any form, then the pre-signed transactions can be used for the deployments. For chains that do not support pre-EIP-155 transactions, a predeploy can be added (as an example, my old Create2Deployer was added to the OP stack as a predeploy, see here). If this is not supported for a chain
X
,CreateX
can't be deployed on this particular chainX
. Everyone who interacts withCreateX
must be aware of this risk.
- Answer: Me and @mds1 each have a copy of the private key to be a backup for each other. We keep the private key very secure, but there is always the risk that we could both lose the private key together one day. I can't go into detail about how we store it (for obvious reasons), but I can assure you that I keep several copies myself in safe places. So what exactly is the risk for this scenario: Assuming we have lost the private key, but not leaked in any form, then the pre-signed transactions can be used for the deployments. For chains that do not support pre-EIP-155 transactions, a predeploy can be added (as an example, my old Create2Deployer was added to the OP stack as a predeploy, see here). If this is not supported for a chain
- Question 2: Risk of leaking the private key of the
CreateX
deployer account0xeD456e05CaAb11d66C4c797dD6c1D6f9A7F352b5
.- Answer: Since in some cases we need to do a private-key-based deployment, the private key is not stored in a cold but in a hot storage. Also, and this is very important, we do not store the private key in a
.env
file or any other file that is part of the repository directory. This prevents an accidental push to the repository as long as we don't copy the private key to a file in the repository that is not.gitignore
d. But, like everything in life, there is no 100% security and the private key could one day be leaked in an unfortunate way. Everyone who interacts withCreateX
must be aware of this risk! For this reason, we have already started to support the 56 most important EVM chains according to TVL, so that any fuckup does not affect these chains. So what exactly is the risk in this scenario (i.e. the private key is leaked)? There are two risks that everyone needs to be aware of:
* Someone else can front-run theCreateX
deployment themselves on a not yet supported chain. The risk is none.
* Someone else can front-run the deployment usingnonce = 0
of theCreateX
deployer account0xeD456e05CaAb11d66C4c797dD6c1D6f9A7F352b5
, but with a maliciousCreateX
contract. The risk is high. For this reason, we recommend that anyone interacting withCreateX
first verifies thekeccak256
-hash of theCreateX
contract creation bytecode, which is0x12ec861579b63a3ab9db3b5a23c57d56402ad3061475b088f17054e2f2daf22f
. This hash can be retrieved via Solidity and using the compiler settings in CreateX.json:
- Answer: Since in some cases we need to do a private-key-based deployment, the private key is not stored in a cold but in a hot storage. Also, and this is very important, we do not store the private key in a
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.23;
import {CreateX} from "./src/CreateX.sol";
contract CreationCodeHashCreateX { function creationCodeHashCreateX() external pure returns (bytes32) { return keccak256(type(CreateX).creationCode); } }
We have sacrificed the beauty of keyless deployment for a fallback option, particularly to be future-proof. In our opinion, this is much more scalable. I add a link to this comment in the README
(see PR #62). @mds1 please add any further insights that I missed. @radeksvarz I hope I was able to address your concerns.
You must be logged in to vote
5 replies
@pcaversaccio Thanks for very open and transparent clarification.
ad Question 1: Risk of losing the private key
While researching MPC and some other co-signing options, I came to idea just to have PK setup with shamir 5/7 with distribution among key public good projects.
I propose that you make somehow backup of deployer's PK in some encrypted form and store that with e.g. ETH Foundation or some other trusted party. This should decrease the probability of the risk of losing PK.
ad Question 2: Risk of leaking the private key
Not sure that it could help now, anyway - I was planning to use Trezor / Keystone HW for signing, so PK would not leave the device. I guess you could import BIP39 seed of the PK if you have that. This can significantly decrease risk of leaking the PK.
ad front running risk and crosschecking the code - I rather check deployed runtime code:
> cast keccak $(cast code 0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed --flashbots)
0xbd8a7ea8cfca7b4e5f5041d7d4b17bc317c5ce42cfbc42066a00cf26b43eb53f
note for others: --flashbots
are for mainnet, use --rpc-url RPC_URL
for other chains
While researching MPC and some other co-signing options, I came to idea just to have PK setup with shamir 5/7 with distribution among key public good projects. I propose that you make somehow backup of deployer's PK in some encrypted form and store that with e.g. ETH Foundation or some other trusted party. This should decrease the probability of the risk of losing PK.
The (based 馃槃) private key for 0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed
was securely mined using profanity2 and thus an SSS algorithm doesn't work here. I know SSS or threshold signature schemes pretty well from my old Bitcoin days. These approaches don't work here, unfortunately, otherwise we would have done so. There is a zero chance that I will store our encrypted PK with any other parties, am sorry. The PK is already safely backed up (multiple times; including an air-gapped computer) over two continents and the only person I trust for this setup is @mds1. I write this here publicly so anyone is aware of this deliberate choice.
Not sure that it could help now, anyway - I was planning to use Trezor / Keystone HW for signing, so PK would not leave the device. I guess you could import BIP39 seed of the PK if you have that. This can significantly decrease risk of leaking the PK.
As mentioned above, the private key for 0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed
was securely mined using profanity2 and thus no BIP39 seed is available for this case.
I can confirm that the runtime bytecode hash of CreateX
is 0xbd8a7ea8cfca7b4e5f5041d7d4b17bc317c5ce42cfbc42066a00cf26b43eb53f
. The reason why I prefer referring to the contract creation bytecode is that it's easier to obtain the original benchmark hash via Solidity:
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.23;
import {CreateX} from "./src/CreateX.sol";
contract BytecodeHashesCreateX {
function creationCodeHashCreateX() external pure returns (bytes32) {
// This works and returns 0x12ec861579b63a3ab9db3b5a23c57d56402ad3061475b088f17054e2f2daf22f
.
return keccak256(type(CreateX).creationCode);
}
function runtimeCodeHashCreateX() external pure returns (bytes32) {
// This doesn't work since the type information `runtimeCode` doesn't work for contracts containing immutable variables, which `CreateX` does.
return keccak256(type(CreateX).runtimeCode);
}
}
FWIW, I document those two hashes in the README
(see PR #64).
I really welcome your transparency on this. It is crucial for users to understand the risks.
There is a zero chance that I will store our encrypted PK with any other parties, am sorry. The PK is already safely backed up (multiple times; including an air-gapped computer) over two continents and the only person I trust for this setup is @mds1. I write this here publicly so anyone is aware of this deliberate choice.
Is there any procedure in place when one (or both) of you becomes permanently unavailable for the deployment requests? (not that I wish you to).
Is there any procedure in place when one (or both) of you becomes permanently unavailable for the deployment requests? (not that I wish you to).
There are two scenarios:
- Target chain supports pre-EIP-155 transactions: Use our pre-signed transactions for the deployment. No interactions from us needed.
- Target chain doesn't support pre-EIP-155 transactions: Open a discussion with the chain's core devs to add
CreateX
as a predeploy. No interactions from us needed but will be time-consuming and slow.
I would argue that 90% (at least) of the chains are covered by scenario 1). For scenario 2), the community can push for the deployment without us being part of it.
As an interesting addendum: This morning I discovered that Geth has disabled sending (!= network layer validation, which is still possible) pre-EIP-155 transactions, thus making it even harder to use a keyless deployment approach. See my tweet here.