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

Batched transactions (implements NEP#0008) #1140

Merged
merged 7 commits into from
Aug 12, 2019
Merged

Conversation

evgenykuzyakov
Copy link
Collaborator

@evgenykuzyakov evgenykuzyakov commented Aug 6, 2019

Some tests still fail. It's more to see what files are modified with some auto-replace.

Fixes: #1032

@evgenykuzyakov evgenykuzyakov changed the title [WIP] Batched transactions Batched transactions (implements NEP#0008) Aug 6, 2019
@evgenykuzyakov evgenykuzyakov marked this pull request as ready for review August 6, 2019 22:51
@evgenykuzyakov
Copy link
Collaborator Author

Benches (my macbook pro):

running 8 tests
test runtime_send_money                     ... bench:     154,154 ns/iter (+/- 21,694)
test runtime_wasm_bad_code                  ... bench:     175,364 ns/iter (+/- 17,458)
test runtime_wasm_benchmark_10_reads_legacy ... bench:     375,788 ns/iter (+/- 18,445)
test runtime_wasm_benchmark_storage_100     ... bench:     753,850 ns/iter (+/- 116,437)
test runtime_wasm_benchmark_storage_1000    ... bench:   5,224,499 ns/iter (+/- 364,528)
test runtime_wasm_benchmark_sum_1000        ... bench:     274,094 ns/iter (+/- 32,330)
test runtime_wasm_benchmark_sum_1000000     ... bench:   8,004,363 ns/iter (+/- 342,908)
test runtime_wasm_set_value                 ... bench:     284,366 ns/iter (+/- 29,012)

@evgenykuzyakov
Copy link
Collaborator Author

Previous benches for comparison:

running 8 tests
test runtime_send_money                     ... bench:     148,466 ns/iter (+/- 7,579)
test runtime_wasm_bad_code                  ... bench:     176,975 ns/iter (+/- 11,976)
test runtime_wasm_benchmark_10_reads_legacy ... bench:     375,113 ns/iter (+/- 66,967)
test runtime_wasm_benchmark_storage_100     ... bench:     742,443 ns/iter (+/- 58,517)
test runtime_wasm_benchmark_storage_1000    ... bench:   5,192,146 ns/iter (+/- 420,130)
test runtime_wasm_benchmark_sum_1000        ... bench:     265,274 ns/iter (+/- 16,762)
test runtime_wasm_benchmark_sum_1000000     ... bench:   8,006,420 ns/iter (+/- 967,673)
test runtime_wasm_set_value                 ... bench:     279,371 ns/iter (+/- 20,418)

chain/chain/src/test_utils.rs Outdated Show resolved Hide resolved
chain/client/src/view_client.rs Outdated Show resolved Hide resolved
core/primitives/src/transaction.rs Show resolved Hide resolved
core/primitives/src/transaction.rs Outdated Show resolved Hide resolved
core/primitives/src/transaction.rs Show resolved Hide resolved
core/primitives/src/transaction.rs Show resolved Hide resolved
core/primitives/src/transaction.rs Show resolved Hide resolved
core/primitives/src/receipt.rs Show resolved Hide resolved
core/primitives/src/receipt.rs Show resolved Hide resolved
core/primitives/src/transaction.rs Outdated Show resolved Hide resolved
core/primitives/src/transaction.rs Outdated Show resolved Hide resolved
core/primitives/src/transaction.rs Outdated Show resolved Hide resolved
@@ -50,10 +49,12 @@ fn kv_to_state_record(key: Vec<u8>, value: DBValue) -> StateRecord {
StateRecord::Account { account_id: to_printable(&key[1..]), account }
}
}
/*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete?

@@ -86,9 +87,11 @@ fn print_state_entry(key: Vec<u8>, value: DBValue) {
to_printable(&from_base64(&value).unwrap())
);
}
/*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not?

@@ -16,8 +15,7 @@ pub enum StateRecord {
Contract { account_id: AccountId, code: String },
/// Access key associated with some account.
AccessKey { account_id: AccountId, public_key: ReadablePublicKey, access_key: AccessKey },
/// Callback.
Callback { id: Vec<u8>, callback: Callback },
// TODO: DATA
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need it for state dump to work, right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Will push it separately

@evgenykuzyakov evgenykuzyakov force-pushed the batched-tx-1 branch 2 times, most recently from b1b57cb to ccba8e1 Compare August 9, 2019 17:46
Copy link
Contributor

@MaksymZavershynskyi MaksymZavershynskyi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of the gas-related stuff will later go into near-vm-logic.

@@ -25,13 +25,10 @@ pub struct BlockHeader {
/// Height of this block since the genesis block (height 0).
pub height: BlockIndex,
/// Hash of the block previous to this in the chain.
#[serde(with = "base_format")]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we don't use base here anymore?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've implemented it for basic types. It helps to avoid things like Vec to have a type for base_vec_bytes_format.

@@ -150,6 +192,25 @@ impl TryFrom<&str> for SecretKey {
}
}

impl Serialize for SecretKey {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks a bit weird. Where do we need to serialize the PublicKey without going through the proto? When returning through RPC as JSON? When override Serialize like that we affect any type of serializer, which is kinda fine for now since we probably only serialize it as JSON at the moment, but if someone later in some crate serializes it with bincode (e.g. for cache) it will also go through base encoding which is unnecessary.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's currently for serde serialization as json.

/// Identifier for callbacks, used to store storage and refer in receipts.
pub type CallbackId = Vec<u8>;
/// Gas is a type for storing amount of gas.
pub type Gas = u64;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gas seems fine to me, since we don't have different underlying types for GasUsed, GasBurnt etc (for the contrast for storage we had StorageUsage and StorageUsageChange because one is u64 and another is i64). It is not part of the protobuf or the protocol, so we can always change it later if we find it confusing or our code gets more complex.

runtime/runtime/src/actions.rs Outdated Show resolved Hide resolved
runtime/runtime/src/actions.rs Outdated Show resolved Hide resolved
stake: &StakeAction,
) {
let mut account = account.as_mut().unwrap();
let increment = if stake.stake > account.staked { stake.stake - account.staked } else { 0 };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it how we stake? If I staked already X and I want to increase my stake to X+Y then I issue a staking transaction with value X+Y instead of Y, correct?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

pub add_key: Balance,
pub delete_key: Balance,
pub delete_account: Balance,
pub struct TransactionCosts {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This structure might need to go entirely into near-vm-logic.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is what I start to wonder. If we decide to charge for every byte of the message (e.g. for args over network). This logic might need to be replicated with the VM, since both of them should produce same Gas cost results.

Copy link
Contributor

@MaksymZavershynskyi MaksymZavershynskyi Aug 9, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest we do the following:
For each binding function of VM we define a cost function: F(args, result)->Gas. Which represents the fees that will be applied to call this function, including side-effects like creating receipts. We have this function in near-vm-logic and the runtime crate receives this information as part of used_gas.

Pros:

  • The logic is encapsulated in near-vm-logic which means it can be used for unit tests in smart contracts. People can write a smart contract, cover it with unit tests and if they did good job with coverage they can expect it to work 100% on the blockchain, because anything not covered by near-vm-* is guaranteed by the rest of engine (like receipts delivery, etc).
  • Our economics-related stuff is in one place, so we do a good job testing it to prevent all kinds of attacks, secondary markets, etc. We might even succeed formalizing it into an economic model.

Cons:

  • F(args, result)->Gas will not represent the actual cost of sending a receipt over the network, including serialization etc. However, independently on our architecture we cannot devise a function (whether it is in runtime or near-vm-logic) that can encapsulate all side-effects and costs, so it will always be an approximation. For instance we do not account for temporary storage that cross-contract calls create in the trie because we cannot measure how many nodes deep it will be, etc. So I suggest we always think of this fee as an approximation, and since it is an approximation, why not keep it in near-vm-logic.

@MaksymZavershynskyi
Copy link
Contributor

FYI this PR did not fix expensive tests, some of them do not even compile, to see run tests like this:

cargo test --all --features expensive_tests

@MaksymZavershynskyi MaksymZavershynskyi dismissed their stale review August 11, 2019 21:23

Expensive tests are broken

@MaksymZavershynskyi
Copy link
Contributor

Related: #1156

evgenykuzyakov and others added 4 commits August 12, 2019 10:33
Co-Authored-By: Maksym Zavershynskyi <35039879+nearmax@users.noreply.github.com>
Co-Authored-By: Maksym Zavershynskyi <35039879+nearmax@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants