Skip to content
This repository was archived by the owner on Apr 8, 2022. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 2 additions & 16 deletions Cargo.lock

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

101 changes: 101 additions & 0 deletions Lets talk about verification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
**This description is still approximate and not accurate, we need to define an approach and agree on checks.**

## Draft TransactionVerifier

I suggest adding a structure that will contain:

```rust
pub struct TransactionVerifier<'a, T: frame_system::Config> {
// Pointer to a tx that we have to check
tx: &'a TransactionFor<T>,
// All inputs, to avoid repeated search in the loop
all_inputs_map: BTreeMap<TokenId, TransactionOutputFor<T>>,
// All outputs, to avoid repeated search in the loop
all_outputs_map: BTreeMap<TokenId, TransactionOutputFor<T>>,
// Using TokenId, you can get the entire amount of this token in all inputs
total_value_of_input_tokens: BTreeMap<TokenId, TransactionOutputFor<T>>,
// Using TokenId, you can get the entire amount of this token in all outputs
total_value_of_output_tokens: BTreeMap<TokenId, TransactionOutputFor<T>>,
// A set of transaction verification functions, this approach will allow you to remove unnecessary cycles, which will speed up the function
set_of_checks: Vec<&'a mut FnMut(...)>,
// ...
// I may add a priority field to the set of checks. I'm still thinking here.
}
```

This struct we will use this way in the pallet utxo:

```rust
pub fn validate_transaction<T: Config>(
tx: &TransactionFor<T>,
) -> Result<ValidTransaction, &'static str> {
TransactionVerifier::<'_, T>::new(tx)
.checking_inputs()
.checking_outputs()
.checking_utxos_exists()
.checking_signatures()
.checking_tokens_transferring()
.checking_tokens_issued()
.checking_nft_mint()
.checking_assets_burn()
.calculating_reward()
.collect_result()?
}

```

When creating a new instance of this structure, we must initialize the fields.

Each subsequent check adds a new instance of the function to `set_of_checks`, which will be called in` collect_result`.

At the moment we can split the verification function for these parts:

* `checking_inputs`
* Checks that inputs exist in a transaction
* Checking that the number of inputs is not more than the maximum allowed number, now in the code I see that it is `u32::MAX`
* Ensure each input is used only a single time

* `checking_outputs`
* Checks that outputs exist in a transaction
* Checking that the number of outputs is not more than the maximum allowed number, now in the code I see that it is `u32::MAX`
* Ensure each output is unique
* Output value must be nonzero
* An output can't exist already in the UtxoStore

* `checking_utxos_exists`
* Resolve the transaction inputs by looking up UTXOs being spent by them.

* `checking_signatures`
* if all spent UTXOs are available, check the math and signatures

* `checking_tokens_transferring`
* We have to check that the total sum of input tokens is less or equal to output tokens. (Or just equal?)
* All inputs with such data code must be correctly mapped to outputs
* If NFT is sent we must not burn or lose data

* `checking_tokens_issued`
* We must check the correctness of the issued tokens
* We have to check the length of `metadata_uri` and` ticker`
* We must check the correctness of `value` and `decimal`

* `checking_nft_mint`
* We have to check the uniqueness of digital data, only one NFT can refer to one object
* We have to check the length of `metadata_uri`

* `checking_assets_burn`
* Is there burn more than possible?
* Is there tocken_id exist for the burn?

* `calculating_reward`
* Just collecting MLT for a transaction reward.
Comment on lines +89 to +90
Copy link
Contributor

Choose a reason for hiding this comment

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

I've understood that the reward can be paid in any token, is that still correct or is that a different kind of reward?

Btw, how do the code changes you've introduced in this PR relate to this proposal?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've understood that the reward can be paid in any token, is that still correct or is that a different kind of reward?

The last thing that I heard, for the test-net we should use only MLT as a reward.

Btw, how do the code changes you've introduced in this PR relate to this proposal?

Added the comment at the top. We need just discus over here.


* `collect_result`
* Call all of these functions in one loop.

## Questions
* Do we need other checks?
* What is we need for checking Bitcoin Script?
* What is we need for checking contracts?
* If we can check an output address here, and add a possibility to find in the UtxoStore by any address format, then we can remove `fn pick_utxo` and `fn send_to_address`. Isn't that?

I'm glad to see any suggestions or critics.
1 change: 0 additions & 1 deletion node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ structopt = '0.3.8'
node-template-runtime = {version = '3.0.0', path = '../runtime'}
pallet-utxo-rpc = { path = "../pallets/utxo/rpc" }
pallet-utxo-rpc-runtime-api = { path = "../pallets/utxo/rpc/runtime-api" }
pallet-utxo-tokens = { path = "../pallets/utxo/tokens" }
log = "0.4.8"
ureq = "2.2.0"

Expand Down
2 changes: 1 addition & 1 deletion node/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ fn testnet_genesis(
.map(|x| {
// may need to create a const variable to represent 1_000 and 100_000_000
pallet_utxo::TransactionOutput::new_pubkey(
1_000 * 100_000_000 * 400_000_000 as pallet_utxo::Value,
1_000 * 100_000_000 * 400_000_000 as pallet_utxo::tokens::Value,
H256::from_slice(x.as_slice()),
)
})
Expand Down
3 changes: 1 addition & 2 deletions pallets/utxo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ std = [
hex-literal = "0.2.1"
log = "0.4.8"
serde = '1.0.119'
pallet-utxo-tokens = { path = "./tokens" }
variant_count = '1.1'

[dependencies.bech32]
Expand All @@ -36,7 +35,7 @@ version = '0.1.0'

[dependencies.codec]
default-features = false
features = ['derive']
features = ["derive", "chain-error"]
package = 'parity-scale-codec'
version = '2.0.0'

Expand Down
7 changes: 6 additions & 1 deletion pallets/utxo/rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ edition = "2018"

[dependencies]
pallet-utxo-rpc-runtime-api = { path = "./runtime-api" }
pallet-utxo-tokens = {path = "../tokens"}
jsonrpc-core = "18.0.0"
jsonrpc-core-client = "18.0.0"
jsonrpc-derive = "18.0.0"
Expand Down Expand Up @@ -44,3 +43,9 @@ default-features = false
git = 'https://github.com/paritytech/substrate.git'
version = '4.0.0-dev'
branch = "master"

[dependencies.sp-core]
default-features = false
git = 'https://github.com/paritytech/substrate.git'
version = '4.0.0-dev'
branch = "master"
9 changes: 6 additions & 3 deletions pallets/utxo/rpc/runtime-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ version = "0.1.0"
authors = ["RBB Lab"]
edition = "2018"

[dependencies]
pallet-utxo-tokens = { path = "../../tokens" }

[dependencies.serde]
version = "1.0.104"
optional = true
Expand Down Expand Up @@ -36,6 +33,12 @@ git = 'https://github.com/paritytech/substrate.git'
version = '4.0.0-dev'
branch = "master"

[dependencies.sp-core]
default-features = false
git = 'https://github.com/paritytech/substrate.git'
version = '4.0.0-dev'
branch = "master"

[dev-dependencies]
serde_json = "1.0.48"

Expand Down
7 changes: 0 additions & 7 deletions pallets/utxo/rpc/runtime-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,8 @@
// Author(s): A. Altonen, Anton Sinitsyn
#![cfg_attr(not(feature = "std"), no_std)]

use frame_support::inherent::Vec;

sp_api::decl_runtime_apis! {
pub trait UtxoApi {
fn send() -> u32;
// What means Vec<(u64, Vec<u8>)> ?
// At the moment we have some problems with use serde in RPC, we can serialize and deserialize
// only simple types. This approach allow us to return Vec<(TokenId, TokenName)> instead of
// pallet_utxo_tokens::TokenListData
fn tokens_list() -> Vec<(u64, Vec<u8>)>;
}
}
18 changes: 0 additions & 18 deletions pallets/utxo/rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ use std::sync::Arc;
pub trait UtxoApi<BlockHash> {
#[rpc(name = "utxo_send")]
fn send(&self, at: Option<BlockHash>) -> Result<u32>;

// What means Vec<(u64, Vec<u8>)> ? Have a look at utxo/rpc/runtime-api/src/lib.rs
#[rpc(name = "tokens_list")]
fn tokens_list(&self, at: Option<BlockHash>) -> Result<Vec<(u64, Vec<u8>)>>;
}

/// A struct that implements the [`UtxoApi`].
Expand Down Expand Up @@ -79,18 +75,4 @@ where
data: Some(format!("{:?}", e).into()),
})
}

fn tokens_list(&self, at: Option<<Block as BlockT>::Hash>) -> Result<Vec<(u64, Vec<u8>)>> {
let api = self.client.runtime_api();
let at = BlockId::hash(at.unwrap_or_else(||
// If the block hash is not supplied assume the best block.
self.client.info().best_hash));

let runtime_api_result = api.tokens_list(&at);
runtime_api_result.map_err(|e| RpcError {
code: ErrorCode::ServerError(Error::StorageError as i64),
message: "Something wrong".into(),
data: Some(format!("{:?}", e).into()),
})
}
}
Loading