Skip to content

Commit

Permalink
Merge pull request #83 from deeper-chain/add-atomos-extrinsics
Browse files Browse the repository at this point in the history
Add add_credit_by_traffic and set_atmos_pubkey
  • Loading branch information
AmadeusGB committed Oct 18, 2021
2 parents 54c8e66 + 175dd2a commit e9c0873
Show file tree
Hide file tree
Showing 16 changed files with 1,003 additions and 11 deletions.
25 changes: 25 additions & 0 deletions Cargo.lock

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

58 changes: 58 additions & 0 deletions pallets/credit-accumulation/Cargo.toml
@@ -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",
]
39 changes: 39 additions & 0 deletions pallets/credit-accumulation/README.md
@@ -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
80 changes: 80 additions & 0 deletions pallets/credit-accumulation/src/benchmarking.rs
@@ -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>());
});
}
}
167 changes: 167 additions & 0 deletions pallets/credit-accumulation/src/lib.rs
@@ -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())
}
}
}

0 comments on commit e9c0873

Please sign in to comment.