How long before a block hash is invalidated? - nearprotocol

The documentation says "Block hash is hash of the block from the current blockchain on top of which this transaction can be applied. It’s used to guard against blockchain forks and rollbacks."
If I try to sign and send a transaction with a block hash that is "a little out of date" then I get the error InvalidTxError::Expired
Is there some specific definition of this expiration timeout that I can use to predict whether it will happen and therefore need to refresh the block hash that I plan to use?
Does it happen after a period of time or if the block hash is Nth from the top of the chain or something?

There is a system-wide parameter transaction_validity_period that defines how long (for how many blocks) a transaction can be considered valid since the block hash it is based on.

after a little more digging based on #berryguy's accepted answer above, it looks like transaction_validity_period is an incoming parameter to ChainGenesis (pressing the blockchain start button, I guess) where the validity period is measured as a BlockIndex ("down from the top" or "back from the tip" of the chain depending on the animation playing out in your head)
snip from nearcore source
pub struct ChainGenesis {
pub time: DateTime<Utc>,
pub gas_limit: Gas,
pub gas_price: Balance,
pub total_supply: Balance,
pub max_inflation_rate: u8,
pub gas_price_adjustment_rate: u8,
pub transaction_validity_period: BlockIndex, /// <- here
pub epoch_length: BlockIndex,
}
and gets populated by genesis configuration file genesis.json that's loaded from ~/.near/genesis.json (on my local machine) maybe by a call to start_with_config

Related

How can i know the balance of the account where the contract is deployed from a method?

I´m trying to write a function that returns the balance of the account where the contract is deployed.
Something with the following form:
pub fn get_balance(&self) -> Balance {
env::account_balance()
}
The above code returns the balance of the account that is calling the method, the signer. Is there a way to make it returns the balance of the contract account?
I got the answer. near_sdk:env::account_balance() already do what i was looking for. It retrieves the balance of the contract account.
I was lacking a way to check it properly. To do it, i used near state [account_name] on the cli to verify if the balance returned was the master or subaccount (where the contract was deployed) balance.
So the answer would be:
pub fn get_balance(&self) -> Balance {
env::account_balance()
}
noting that to have the transferible balance, it would have to take into account the min balance used for storage.

Balances AccountStore definition in substrate runtime

In the balances pallet, the config trait has one item that is defined like type AccountStore: StoredMap<Self::AccountId, AccountData<Self::Balance>>;. This was a bit strange to me as I was expecting a normal storage map to store a mapping from AccountId to AccountData but after I looked at the docs for StoredMap I realised that it's a trait implemented on StorageMaps as well. That makes more sense now, so I go on to look at how the runtime defines this field, and to my surprise I find this in the runtime/src/lib.rs : type AccountStore = System;. Now I've never seen a runtime definition like this before because if I'm correct, System is supposed to represent the frame_system pallet. So I go to look at frame_system::Config for Runtime and I find this defintion :
type AccountData = pallet_balances::AccountData<Balance>;.
Now I don't know how these definitions are getting into pallet_balances' Config impl, but I can see that System contains both ingredients namely : one type AccountData and one AccountId. So at the end my two questions that stand are
What are the reasons for such a convulting design?
How does type AccountStore = System; figure out the concrete types?
Storing account balances in the system pallet also maintains some other frame_system information that may be important to keep around for a certain runtime configuration. But having consumers, providers and sufficients inside a runtime with multiple pallets and potentially interacting with other runtimes becomes quite crucial.
AccountStore defines where this balance is going to be stored, for this case is frame_system::Pallet<Runtime>. If we follow the lead and check the configuration of frame_system we will see that the type for AccountData is defined as
type AccountData = pallet_balances::AccountData<Balance>
Good, now we know that the AccountData stored in frame_system will be the one defined in pallet_balances.
So the information living in system concerning accounts will end up looking like the following:
/// Information of an account.
#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo)]
pub struct AccountInfo<Index, AccountData> {
/// The number of transactions this account has sent.
pub nonce: Index,
/// The number of other modules that currently depend on this account's existence. The account
/// cannot be reaped until this is zero.
pub consumers: RefCount,
/// The number of other modules that allow this account to exist. The account may not be reaped
/// until this and `sufficients` are both zero.
pub providers: RefCount,
/// The number of modules that allow this account to exist for their own purposes only. The
/// account may not be reaped until this and `providers` are both zero.
pub sufficients: RefCount,
/// The additional data that belongs to this account. Used to store the balance(s) in a lot of
/// chains.
pub data: AccountData,
}
Where AccountData fits the previous mentioned definition in pallet_balances.
Please, check this commit too for further information on how this may be tweaked -> https://github.com/paritytech/substrate/commit/31d90c202d6df9ce3837ee55587b604619a912ba

Near protocol equivalent of buring NEAR tokens by sending to address(0)

I want to delete the current contract and burn its NEAR balance when a condition is triggered.
Here's the Solidity version:
selfdestruct(address(0));
I found Promise::delete_account in the Rust SDK but it has a beneficiary_address field. Ideally the funds should be gone forever and not transferred to an owned address.
Promise::new(env::current_account_id()).delete_account(beneficiary_address);
address(0) is address 0x0, a black hole address used to burn Ether.
Currently there is no API to burn NEAR tokens directly. One workaround is to set the beneficiary account id to system. system is an account that can never be created and is used internally for refunds. When the beneficiary account does not exist, the tokens transferred through account deletion are automatically burnt.
I think that is like this:
#[payable]
pub fn burn() {
Promise::new("system".to_string()).transfer(env::attached_deposit());
}
First importing:
use near_sdk::{Promise};

When chaining multiple executions with callbacks how to allocate gas

If there is a chain of actions that need to be executed inside NEAR's smart contract and is chained via callbacks from given contract - how to allocate gas for them.
For example:
pub fn some_method(&mut self, ...) -> Promise {
...
Promise::new(other_contract).function_call(...).then(
ext_self::callback(env::current_account_id(), 0, ????)
)
}
pub fn callback(&mut self) -> PromiseOrValue<bool> {
if some_condition {
self.some_method(...)
} else {
PromiseOrValue::Value(true)
}
}
What should be ???? to correctly allocate gas for this chain of actions?
The correct amount of gas allocation depends on the remote method. The amount of gas is just the amount of prepaid gas that will be available at the remote function call. It doesn't include fees for calling the contract or creating a promise. They will charged separately.
The fees can be vary based on what the remote method is going to do.
Let's say it's just a simple local method without external promises. If it doesn't do a lot of compute and doesn't access a lot of storage, then the execution of it going to be fairly cheap. So you may attach about 10**13 gas.
But if the remote method is going to call other promises and make external calls, or has heavier compute, then you need to account for this.
It's also the case for the local callback that you attach using .then. Use the same logic when estimating the amount of prepaid gas needed.

do all NEAR blockchain transactions require a receiver account?

reading through some documentation here and saw that part of the definition of a transaction is that all actions are performed "on top of the receiver's account" and also that the receiver account is "the account towards which the transaction will be routed."
also in the nearlib SDK, the transactions interface includes a method called signTransaction that requires receiverId as a parameter
async function signTransaction(receiverId: string, nonce: number, actions: Action[], blockHash: Uint8Array, signer: Signer, accountId?: string, networkId?: string): Promise<[Uint8Array, SignedTransaction]> {
but looking over the list of transactions supported by nearcore I wonder why do some of these transaction require a receiver.
why would any transactions require a "receiver" except for maybe Transfer, AddKey, DeleteKey, and DeleteAccount?
amd I think of the idea of "receiver" too literally, as in "they receive the outcome or impact of the transaction"? and instead it's not the right way to think about it?
or is receiverId optional in some cases but the interface just requires a value to avoid validation cruft?
here's what I believe to be the full list of supported transactions
pub enum Action {
CreateAccount(CreateAccountAction),
DeployContract(DeployContractAction),
FunctionCall(FunctionCallAction),
Transfer(TransferAction),
Stake(StakeAction),
AddKey(AddKeyAction),
DeleteKey(DeleteKeyAction),
DeleteAccount(DeleteAccountAction),
}
Conceptually every transaction always has a sender and a receiver, even though sometimes they might be the same. Because we always convert a transaction to a receipt that is sent to the receiver, it doesn't matter conceptually whether they are the same, even though in implementation there might be a difference.
Unfortunately, we don't have a good name to denote what we call "receiver". In some places in our code, we also call it "actor", because it actually refers to an account on which the action is performed opposed to an account which issued the action to perform (a.k.a "sender").
DeployContract, Stake, AddKey, DeleteKey require receiver==sender, in other words only an account itself can add/delete keys, stake and deploy a contract on itself, no other account can do it for it.
DeleteAccount is the same, it requires receiver==sender with one exception: If account is about to run out of balance due to storage rent and is below certain system-defined treshold any other account can delete it and claim the remaining balance.
CreateAccount, FunctionCall, and Transfer do not require receiver==sender. In case of the CreateAccount receiver should not exist at the moment of execution and will actually be created.
See the code that implements this logic: https://github.com/nearprotocol/nearcore/blob/ed43018851f8ec44f0a26b49fc9a863b71a1428f/runtime/runtime/src/actions.rs#L360

Resources