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
use super::{Address, H256, U256};
use keccak_hash::keccak;
use rlp::RlpStream;
/// Specifies how an address is calculated for a new contract.
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub enum CreateContractAddressType {
/// Address is calculated from sender and nonce. Ethereum
/// `create` scheme.
FromSenderNonce,
/// Address is calculated from sender, nonce, and code hash. Conflux
/// `create` scheme.
FromSenderNonceAndCodeHash,
/// Address is calculated from block_hash, sender, nonce and code_hash.
/// Potential new Conflux `create` scheme when kill_dust is enabled.
FromBlockNumberSenderNonceAndCodeHash,
/// Address is calculated from sender, salt and code hash. Conflux and
/// Ethereum `create2` scheme.
FromSenderSaltAndCodeHash(H256),
}
/// Calculate new contract address.
pub fn cal_contract_address(
address_scheme: CreateContractAddressType, _block_number: u64,
sender: &Address, nonce: &U256, code: &[u8],
) -> (Address, H256) {
let code_hash = keccak(code);
let (address, code_hash) = match address_scheme {
CreateContractAddressType::FromSenderNonce => {
let mut rlp = RlpStream::new_list(2);
rlp.append(sender);
rlp.append(nonce);
let h = Address::from(keccak(rlp.as_raw()));
(h, code_hash)
}
CreateContractAddressType::FromBlockNumberSenderNonceAndCodeHash => {
unreachable!("Inactive setting");
// let mut buffer = [0u8; 1 + 8 + 20 + 32 + 32];
// let (lead_bytes, rest) = buffer.split_at_mut(1);
// let (block_number_bytes, rest) = rest.split_at_mut(8);
// let (sender_bytes, rest) =
// rest.split_at_mut(Address::len_bytes());
// let (nonce_bytes, code_hash_bytes) =
// rest.split_at_mut(H256::len_bytes());
// // In Conflux, we take block_number and CodeHash into address
// // calculation. This is required to enable us to clean
// // up unused user account in future.
// lead_bytes[0] = 0x0;
// block_number.to_little_endian(block_number_bytes);
// sender_bytes.copy_from_slice(&sender.address[..]);
// nonce.to_little_endian(nonce_bytes);
// code_hash_bytes.copy_from_slice(&code_hash[..]);
// // In Conflux, we use the first four bits to indicate the type of
// // the address. For contract address, the bits will be
// // set to 0x8.
// let mut h = Address::from(keccak(&buffer[..]));
// h.set_contract_type_bits();
// (h, code_hash)
}
CreateContractAddressType::FromSenderNonceAndCodeHash => {
let mut buffer = [0u8; 1 + 20 + 32 + 32];
// In Conflux, we append CodeHash to determine the address as well.
// This is required to enable us to clean up unused user account in
// future.
buffer[0] = 0x0;
buffer[1..(1 + 20)].copy_from_slice(&sender[..]);
nonce.to_little_endian(&mut buffer[(1 + 20)..(1 + 20 + 32)]);
buffer[(1 + 20 + 32)..].copy_from_slice(&code_hash[..]);
// In Conflux, we use the first four bits to indicate the type of
// the address. For contract address, the bits will be
// set to 0x8.
let h = Address::from(keccak(&buffer[..]));
(h, code_hash)
}
CreateContractAddressType::FromSenderSaltAndCodeHash(salt) => {
let mut buffer = [0u8; 1 + 20 + 32 + 32];
buffer[0] = 0xff;
buffer[1..(1 + 20)].copy_from_slice(&sender[..]);
buffer[(1 + 20)..(1 + 20 + 32)].copy_from_slice(&salt[..]);
buffer[(1 + 20 + 32)..].copy_from_slice(&code_hash[..]);
// In Conflux, we use the first bit to indicate the type of the
// address. For contract address, the bits will be set to 0x8.
let h = Address::from(keccak(&buffer[..]));
(h, code_hash)
}
};
return (address, code_hash);
}