Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implicit account creation #3251

Merged
merged 14 commits into from
Sep 2, 2020
24 changes: 16 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions chain/chain/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@ impl RuntimeAdapter for KeyValueRuntime {
_state_update: Option<StateRoot>,
_transaction: &SignedTransaction,
_verify_signature: bool,
_current_protocol_version: ProtocolVersion,
) -> Result<Option<InvalidTxError>, Error> {
Ok(None)
}
Expand All @@ -474,6 +475,7 @@ impl RuntimeAdapter for KeyValueRuntime {
_state_root: StateRoot,
transactions: &mut dyn PoolIterator,
_chain_validate: &mut dyn FnMut(&SignedTransaction) -> bool,
_current_protocol_version: ProtocolVersion,
) -> Result<Vec<SignedTransaction>, Error> {
let mut res = vec![];
while let Some(iter) = transactions.next() {
Expand Down
2 changes: 2 additions & 0 deletions chain/chain/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ pub trait RuntimeAdapter: Send + Sync {
state_root: Option<StateRoot>,
transaction: &SignedTransaction,
verify_signature: bool,
current_protocol_version: ProtocolVersion,
) -> Result<Option<InvalidTxError>, Error>;

/// Returns an ordered list of valid transactions from the pool up the given limits.
Expand All @@ -272,6 +273,7 @@ pub trait RuntimeAdapter: Send + Sync {
state_root: StateRoot,
pool_iterator: &mut dyn PoolIterator,
chain_validate: &mut dyn FnMut(&SignedTransaction) -> bool,
current_protocol_version: ProtocolVersion,
) -> Result<Vec<SignedTransaction>, Error>;

/// Verify validator signature for the given epoch.
Expand Down
58 changes: 33 additions & 25 deletions chain/client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ impl Client {
.clone();

let prev_block_header = self.chain.get_block_header(&prev_block_hash)?.clone();
let transactions = self.prepare_transactions(shard_id, &chunk_extra, &prev_block_header);
let transactions = self.prepare_transactions(shard_id, &chunk_extra, &prev_block_header)?;
let num_filtered_transactions = transactions.len();
let (tx_root, _) = merklize(&transactions);
let ReceiptResponse(_, outgoing_receipts) = self.chain.get_outgoing_receipts_for_shard(
Expand Down Expand Up @@ -556,36 +556,40 @@ impl Client {
shard_id: ShardId,
chunk_extra: &ChunkExtra,
prev_block_header: &BlockHeader,
) -> Vec<SignedTransaction> {
) -> Result<Vec<SignedTransaction>, Error> {
let Self { chain, shards_mgr, runtime_adapter, .. } = self;

let next_epoch_id =
runtime_adapter.get_epoch_id_from_prev_block(&prev_block_header.hash())?;
let protocol_version = runtime_adapter.get_epoch_protocol_version(&next_epoch_id)?;

let transactions = if let Some(mut iter) = shards_mgr.get_pool_iterator(shard_id) {
let transaction_validity_period = chain.transaction_validity_period;
runtime_adapter
.prepare_transactions(
prev_block_header.gas_price(),
chunk_extra.gas_limit,
shard_id,
chunk_extra.state_root.clone(),
&mut iter,
&mut |tx: &SignedTransaction| -> bool {
chain
.mut_store()
.check_transaction_validity_period(
&prev_block_header,
&tx.transaction.block_hash,
transaction_validity_period,
)
.is_ok()
},
)
.expect("no StorageError please")
runtime_adapter.prepare_transactions(
prev_block_header.gas_price(),
chunk_extra.gas_limit,
shard_id,
chunk_extra.state_root.clone(),
&mut iter,
&mut |tx: &SignedTransaction| -> bool {
chain
.mut_store()
.check_transaction_validity_period(
&prev_block_header,
&tx.transaction.block_hash,
transaction_validity_period,
)
.is_ok()
},
protocol_version,
)?
} else {
vec![]
};
// Reintroduce valid transactions back to the pool. They will be removed when the chunk is
// included into the block.
shards_mgr.reintroduce_transactions(shard_id, &transactions);
transactions
Ok(transactions)
}

pub fn send_challenges(&mut self, challenges: Arc<RwLock<Vec<ChallengeBody>>>) {
Expand Down Expand Up @@ -1225,8 +1229,12 @@ impl Client {
let gas_price = cur_block_header.gas_price();
let epoch_id = self.runtime_adapter.get_epoch_id_from_prev_block(&head.last_block_hash)?;

if let Some(err) =
self.runtime_adapter.validate_tx(gas_price, None, &tx, true).expect("no storage errors")
let protocol_version = self.runtime_adapter.get_epoch_protocol_version(&epoch_id)?;

if let Some(err) = self
.runtime_adapter
.validate_tx(gas_price, None, &tx, true, protocol_version)
.expect("no storage errors")
{
debug!(target: "client", "Invalid tx during basic validation: {:?}", err);
return Ok(NetworkClientResponses::InvalidTx(err));
Expand All @@ -1252,7 +1260,7 @@ impl Client {
};
if let Some(err) = self
.runtime_adapter
.validate_tx(gas_price, Some(state_root), &tx, false)
.validate_tx(gas_price, Some(state_root), &tx, false, protocol_version)
.expect("no storage errors")
{
debug!(target: "client", "Invalid tx: {:?}", err);
Expand Down
10 changes: 9 additions & 1 deletion chain/jsonrpc/res/rpc_errors_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,8 @@
"TriesToStake",
"InsufficientStake",
"FunctionCallError",
"NewReceiptValidationError"
"NewReceiptValidationError",
"OnlyImplicitAccountCreationAllowed"
],
"props": {
"index": ""
Expand Down Expand Up @@ -718,6 +719,13 @@
"signer_id": ""
}
},
"OnlyImplicitAccountCreationAllowed": {
"name": "OnlyImplicitAccountCreationAllowed",
"subtypes": [],
"props": {
"account_id": ""
}
},
"ReceiptValidationError": {
"name": "ReceiptValidationError",
"subtypes": [
Expand Down
4 changes: 2 additions & 2 deletions core/crypto/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{InMemorySigner, Signature};

fn ed25519_key_pair_from_seed(seed: &str) -> ed25519_dalek::Keypair {
let seed_bytes = seed.as_bytes();
let len = seed_bytes.len();
let len = std::cmp::min(ed25519_dalek::SECRET_KEY_LENGTH, seed_bytes.len());
let mut seed: [u8; ed25519_dalek::SECRET_KEY_LENGTH] = [b' '; ed25519_dalek::SECRET_KEY_LENGTH];
seed[..len].copy_from_slice(&seed_bytes[..len]);
let secret = ed25519_dalek::SecretKey::from_bytes(&seed).unwrap();
Expand All @@ -17,7 +17,7 @@ fn ed25519_key_pair_from_seed(seed: &str) -> ed25519_dalek::Keypair {

fn secp256k1_secret_key_from_seed(seed: &str) -> secp256k1::key::SecretKey {
let seed_bytes = seed.as_bytes();
let len = seed_bytes.len();
let len = std::cmp::min(32, seed_bytes.len());
let mut seed: [u8; 32] = [b' '; 32];
seed[..len].copy_from_slice(&seed_bytes[..len]);
let mut rng: StdRng = rand::SeedableRng::from_seed(seed);
Expand Down
6 changes: 5 additions & 1 deletion core/primitives/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,9 @@ pub enum ActionErrorKind {
/// Error occurs when a new `ActionReceipt` created by the `FunctionCall` action fails
/// receipt validation.
NewReceiptValidationError(ReceiptValidationError),
/// Error occurs when a `CreateAccount` action is called on hex-characters account of length 64.
/// See implicit account creation NEP: https://github.com/nearprotocol/NEPs/pull/71
OnlyImplicitAccountCreationAllowed { account_id: AccountId },
}

impl From<ActionErrorKind> for ActionError {
Expand Down Expand Up @@ -670,7 +673,8 @@ impl Display for ActionErrorKind {
ActionErrorKind::NewReceiptValidationError(e) => {
write!(f, "An new action receipt created during a FunctionCall is not valid: {}", e)
}
ActionErrorKind::InsufficientStake { account_id, stake, minimum_stake } => write!(f, "Account {} tries to stake {} but minimum required stake is {}", account_id, stake, minimum_stake)
ActionErrorKind::InsufficientStake { account_id, stake, minimum_stake } => write!(f, "Account {} tries to stake {} but minimum required stake is {}", account_id, stake, minimum_stake),
ActionErrorKind::OnlyImplicitAccountCreationAllowed { account_id } => write!(f, "CreateAccount action is called on hex-characters account of length 64 {}", account_id)
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion core/primitives/src/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub const DB_VERSION: DbVersion = 8;
pub type ProtocolVersion = u32;

/// Current latest version of the protocol.
pub const PROTOCOL_VERSION: ProtocolVersion = 34;
pub const PROTOCOL_VERSION: ProtocolVersion = 35;
/// Oldest supported version by this client.
pub const OLDEST_BACKWARD_COMPATIBLE_PROTOCOL_VERSION: ProtocolVersion = 29;

Expand All @@ -31,3 +31,6 @@ pub const MIN_GAS_PRICE_NEP_92_FIX: Balance = 100_000_000;
pub const MIN_PROTOCOL_VERSION_NEP_92_FIX: ProtocolVersion = 32;

pub const CORRECT_RANDOM_VALUE_PROTOCOL_VERSION: ProtocolVersion = 33;

/// See [NEP 71](https://github.com/nearprotocol/NEPs/pull/71)
pub const IMPLICIT_ACCOUNT_CREATION_PROTOCOL_VERSION: ProtocolVersion = 35;
4 changes: 2 additions & 2 deletions neard/res/genesis_config.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"protocol_version": 34,
"protocol_version": 35,
"genesis_time": "1970-01-01T00:00:00.000000000Z",
"chain_id": "sample",
"genesis_height": 0,
Expand Down Expand Up @@ -236,4 +236,4 @@
"fishermen_threshold": "10000000000000000000000000",
"minimum_stake_divisor": 10,
"records": []
}
}
Loading