Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #83 from deeper-chain/add-atomos-extrinsics
Add add_credit_by_traffic and set_atmos_pubkey
- Loading branch information
Showing
16 changed files
with
1,003 additions
and
11 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
[package] | ||
authors = ['Deeper Network'] | ||
edition = '2018' | ||
name = 'pallet-credit-accumulation' | ||
version = "3.0.0" | ||
homepage = "https://deeper.network" | ||
repository = "https://github.com/deeper-chain/deeper-chain" | ||
description = "pallet-credit-accumulation" | ||
readme = "README.md" | ||
|
||
[package.metadata.docs.rs] | ||
targets = ["x86_64-unknown-linux-gnu"] | ||
|
||
[dependencies] | ||
log = { default-features = false, version = "0.4.11" } | ||
blake2-rfc = { version = "0.2.18", default-features = false } | ||
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } | ||
frame-support = {default-features = false, git = "https://github.com/paritytech/substrate", tag = "v3.0.0" } | ||
frame-system = {default-features = false, git = "https://github.com/paritytech/substrate", tag = "v3.0.0" } | ||
pallet-timestamp = {default-features = false, git = "https://github.com/paritytech/substrate", tag = "v3.0.0" } | ||
node-primitives = {version = '2.0.0', default-features = false, path = "../../primitives"} | ||
pallet-balances = { version = "3.0.0", default-features = false, path = "../balances"} | ||
pallet-credit = { default-features = false, path = "../credit", version = "3.0.0" } | ||
pallet-deeper-node = { version = "3.0.0", default-features = false, path = "../deeper-node"} | ||
pallet-micropayment = { version = "3.0.0", default-features = false, path = "../micropayment"} | ||
sp-core = {default-features = false, git = "https://github.com/paritytech/substrate", tag = "v3.0.0" } | ||
sp-io = {default-features = false, git = "https://github.com/paritytech/substrate", tag = "v3.0.0" } | ||
sp-runtime = {default-features = false, git = "https://github.com/paritytech/substrate", tag = "v3.0.0" } | ||
sp-std = {default-features = false, git = "https://github.com/paritytech/substrate", tag = "v3.0.0" } | ||
# Optional imports for benchmarking | ||
frame-benchmarking = { default-features = false, git = "https://github.com/paritytech/substrate", tag = "v3.0.0", optional = true } | ||
hex-literal = "0.3.1" | ||
|
||
[dev-dependencies] | ||
frame-benchmarking = { git = "https://github.com/paritytech/substrate", tag = "v3.0.0" } | ||
serde = { version = "1.0.101" } | ||
|
||
[features] | ||
default = ['std'] | ||
std = [ | ||
'codec/std', | ||
'frame-support/std', | ||
'frame-system/std', | ||
'sp-io/std', | ||
'sp-runtime/std', | ||
'sp-core/std', | ||
'sp-std/std', | ||
'pallet-timestamp/std', | ||
'node-primitives/std', | ||
'pallet-balances/std', | ||
'pallet-credit/std', | ||
'pallet-deeper-node/std', | ||
'pallet-micropayment/std', | ||
'log/std', | ||
] | ||
runtime-benchmarks = [ | ||
"frame-benchmarking", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# Credit-Accumulation Pallet | ||
|
||
The credit-accumulation pallet provides functionality for Deeper Connect devices to accumulate credit score by traffic. | ||
|
||
## Overview | ||
|
||
The credit-accumulation pallet provides the following functions: | ||
|
||
- submit a signature to accumulate credit score | ||
- set atmos pubkey | ||
|
||
|
||
### Terminology | ||
|
||
- **Nonce:** An index that indicates an occurring of sigature to accumulate credit score. It starts with 0 and increment by 1 each time. | ||
|
||
## Interface | ||
|
||
### Dispatchable Functions | ||
|
||
- `add_credit_by_traffic` - an Atmos submit a signature to accumulate credit score. | ||
- `set_atmos_pubkey` - root to set atmos pubkey. | ||
|
||
## Usage | ||
|
||
This pallet only provides dispatchable functions to end users. | ||
|
||
Run `cargo build` in terminal to build this pallet. | ||
Run `cargo test` in terminal to run the unit tests. | ||
|
||
## Genesis config | ||
|
||
There is nothing to config for this pallet in genesis. | ||
|
||
## Dependencies | ||
|
||
This pallet depends on the CreditInterface trait. It's not a general purpose pallet that can be used elsewhere, but we hope the concepts and interfaces can be useful for other projects. | ||
|
||
License: Apache-2.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
//! Micropayment pallet benchmarking. | ||
|
||
use super::*; | ||
use crate::Module as CreditAccumulation; | ||
pub use frame_benchmarking::{account, benchmarks, whitelist_account, whitelisted_caller}; | ||
use frame_support::assert_ok; | ||
use frame_support::traits::Currency; | ||
use frame_system::RawOrigin; | ||
use hex_literal::hex; | ||
use pallet_micropayment::AccountCreator; | ||
use sp_std::vec; | ||
|
||
/// Grab a funded user with balance_factor DPR. | ||
pub fn create_funded_user<T: Config>(string: &'static str, balance_factor: u32) -> T::AccountId { | ||
let user = T::AccountCreator::create_account(string); | ||
let balance = T::Currency::minimum_balance() * balance_factor.into(); | ||
T::Currency::make_free_balance_be(&user, balance); | ||
T::Currency::issue(balance); | ||
user | ||
} | ||
|
||
benchmarks! { | ||
add_credit_by_traffic { | ||
let alice = create_funded_user::<T>("Alice", 100); | ||
let bob = create_funded_user::<T>("Bob", 100); | ||
// OK | ||
assert_ok!(CreditAccumulation::<T>::set_atmos_pubkey( | ||
RawOrigin::Root.into(), | ||
bob, | ||
)); | ||
|
||
// OK | ||
let nonce: u64 = 0; | ||
let signature: [u8; 64] = hex!("5071a1a526b1d2d1833e4de43d1ce22ad3506de2e10ee4a9c18c0b310c54286b9cb10bfb4ee12be6b93e91337de0fa2ea2edd787d083db36211109bdc8438989"); | ||
}: _(RawOrigin::Signed(alice.clone()), nonce, signature.into()) | ||
verify { | ||
assert_eq!( | ||
CreditAccumulation::<T>::atmos_nonce(alice), Some(1) | ||
); | ||
} | ||
|
||
set_atmos_pubkey { | ||
let bob = create_funded_user::<T>("Bob", 100); | ||
}: _(RawOrigin::Root, bob.clone()) | ||
verify { | ||
assert_eq!( | ||
CreditAccumulation::<T>::atmos_accountid(), Some(bob) | ||
); | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use crate::mock::{new_test_ext, Test}; | ||
use frame_support::assert_ok; | ||
|
||
#[test] | ||
fn test_benchmarks() { | ||
new_test_ext().execute_with(|| { | ||
assert_ok!(test_benchmark_add_credit_by_traffic::<Test>()); | ||
assert_ok!(test_benchmark_set_atmos_pubkey::<Test>()); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
// Copyright (C) 2021 Deeper Network Inc. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
//! Micropayment pallet for deeper chain | ||
//! | ||
//! This pallet provides functions for Deeper Connect devices to get rewarded | ||
//! for sharing bandwidth. The rewards include payment in DPR tokens and | ||
//! credit accumulation. | ||
|
||
#![cfg_attr(not(feature = "std"), no_std)] | ||
|
||
pub use pallet::*; | ||
|
||
#[cfg(test)] | ||
mod mock; | ||
|
||
#[cfg(test)] | ||
mod tests; | ||
|
||
#[cfg(test)] | ||
pub mod testing_utils; | ||
|
||
#[cfg(any(feature = "runtime-benchmarks", test))] | ||
pub mod benchmarking; | ||
#[cfg(any(feature = "runtime-benchmarks"))] | ||
use sp_std::prelude::*; | ||
|
||
pub mod weights; | ||
|
||
#[frame_support::pallet] | ||
pub mod pallet { | ||
use crate::weights::WeightInfo; | ||
use frame_support::codec::Encode; | ||
use frame_support::traits::{Currency, Vec}; | ||
use frame_support::{dispatch::DispatchResultWithPostInfo, pallet_prelude::*}; | ||
use frame_system::pallet_prelude::*; | ||
use pallet_credit::CreditInterface; | ||
use pallet_micropayment::AccountCreator; | ||
use sp_core::sr25519; | ||
use sp_io::crypto::sr25519_verify; | ||
|
||
/// Configure the pallet by specifying the parameters and types on which it depends. | ||
#[pallet::config] | ||
pub trait Config: frame_system::Config { | ||
// Because this pallet emits events, it depends on the runtime's definition of an event. | ||
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>; | ||
type Currency: Currency<Self::AccountId>; | ||
// CreditInterface of credit pallet | ||
type CreditInterface: CreditInterface<Self::AccountId, BalanceOf<Self>>; | ||
// Create Account trait for benchmarking | ||
type AccountCreator: AccountCreator<Self::AccountId>; | ||
// Weight information for extrinsics in this pallet. | ||
type WeightInfo: WeightInfo; | ||
} | ||
|
||
type BalanceOf<T> = | ||
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance; | ||
|
||
#[pallet::pallet] | ||
#[pallet::generate_store(pub(super) trait Store)] | ||
pub struct Pallet<T>(_); | ||
|
||
// atmos_nonce indicates the next available value; | ||
#[pallet::storage] | ||
#[pallet::getter(fn atmos_nonce)] | ||
pub(super) type AtmosNonce<T: Config> = | ||
StorageMap<_, Blake2_128Concat, T::AccountId, u64, OptionQuery>; | ||
|
||
#[pallet::storage] | ||
#[pallet::getter(fn atmos_accountid)] | ||
pub(super) type AtmosAccountid<T: Config> = StorageValue<_, T::AccountId>; | ||
|
||
#[pallet::event] | ||
#[pallet::metadata(T::AccountId = "AccountId", T::BlockNumber = "BlockNumber")] | ||
#[pallet::generate_deposit(pub(super) fn deposit_event)] | ||
pub enum Event<T: Config> { | ||
AtmosSignatureValid(T::AccountId), | ||
} | ||
|
||
#[pallet::error] | ||
pub enum Error<T> { | ||
// Invalid signature | ||
InvalidSignature, | ||
/// Invalid atomos nonce | ||
InvalidAtomosNonce, | ||
} | ||
|
||
#[pallet::hooks] | ||
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {} | ||
|
||
// Dispatchable functions allows users to interact with the pallet and invoke state changes. | ||
// These functions materialize as "extrinsics", which are often compared to transactions. | ||
// Dispatchable functions must be annotated with a weight and must return a DispatchResult. | ||
#[pallet::call] | ||
impl<T: Config> Pallet<T> { | ||
#[pallet::weight(T::WeightInfo::add_credit_by_traffic())] | ||
pub fn add_credit_by_traffic( | ||
origin: OriginFor<T>, | ||
nonce: u64, | ||
signature: Vec<u8>, | ||
) -> DispatchResultWithPostInfo { | ||
let server = ensure_signed(origin)?; | ||
|
||
let atmos_nonce_of_server = Self::atmos_nonce(&server).unwrap_or_default(); | ||
ensure!( | ||
nonce == atmos_nonce_of_server, | ||
Error::<T>::InvalidAtomosNonce | ||
); | ||
|
||
Self::verify_atomos_signature(nonce, &signature, server.clone())?; | ||
Self::deposit_event(Event::AtmosSignatureValid(server.clone())); | ||
AtmosNonce::<T>::insert(&server, atmos_nonce_of_server + 1u64); | ||
T::CreditInterface::update_credit_by_traffic(server); | ||
Ok(().into()) | ||
} | ||
|
||
#[pallet::weight(T::WeightInfo::set_atmos_pubkey())] | ||
pub fn set_atmos_pubkey( | ||
origin: OriginFor<T>, | ||
pubkey: T::AccountId, | ||
) -> DispatchResultWithPostInfo { | ||
ensure_root(origin)?; | ||
<AtmosAccountid<T>>::put(pubkey); | ||
Ok(().into()) | ||
} | ||
} | ||
|
||
impl<T: Config> Pallet<T> { | ||
pub fn verify_atomos_signature( | ||
nonce: u64, | ||
signature: &Vec<u8>, | ||
sender: T::AccountId, | ||
) -> DispatchResultWithPostInfo { | ||
let mut pk = [0u8; 32]; | ||
let atomos_accountid = Self::atmos_accountid().unwrap_or_default(); | ||
pk.copy_from_slice(&atomos_accountid.encode()); | ||
let pub_key = sr25519::Public::from_raw(pk); | ||
|
||
let mut sig = [0u8; 64]; | ||
sig.copy_from_slice(&signature); | ||
let sig = sr25519::Signature::from_slice(&sig); | ||
|
||
let mut data = Vec::new(); | ||
data.extend_from_slice(&atomos_accountid.encode()); | ||
data.extend_from_slice(&nonce.to_be_bytes()); | ||
data.extend_from_slice(&sender.encode()); | ||
let msg = sp_io::hashing::blake2_256(&data); | ||
|
||
let verified = sr25519_verify(&sig, &msg, &pub_key); | ||
ensure!(verified, Error::<T>::InvalidSignature); | ||
|
||
Ok(().into()) | ||
} | ||
} | ||
} |
Oops, something went wrong.