Skip to content

Commit

Permalink
added a OCW feature to pallet-bank, updated OCW pallet
Browse files Browse the repository at this point in the history
  • Loading branch information
abhi3700 committed Jul 25, 2023
1 parent 662c097 commit fb17c5f
Show file tree
Hide file tree
Showing 9 changed files with 728 additions and 238 deletions.
765 changes: 572 additions & 193 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ members = [
"pallets/voting",
"pallets/lockable-currency",
"pallets/bank",
"pallets/eosio_system",
"pallets/ocw",
"runtime",
]
[profile.release]
Expand Down
9 changes: 4 additions & 5 deletions node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,16 @@ node-template-runtime = { version = "4.0.0-dev", path = "../runtime" }
# CLI-specific dependencies
try-runtime-cli = { version = "0.10.0-dev", optional = true, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" }

# for OCW pallets
# sp-keystore = {version = "0.27.0", optional = true}

[build-dependencies]
substrate-build-script-utils = { version = "3.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" }

[features]
default = []
# Dependencies that are only required if runtime benchmarking should be build.
runtime-benchmarks = [
"node-template-runtime/runtime-benchmarks",
"frame-benchmarking/runtime-benchmarks",
"frame-benchmarking-cli/runtime-benchmarks",
]
runtime-benchmarks = ["node-template-runtime/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", "frame-benchmarking-cli/runtime-benchmarks"]
# Enable features that allow the runtime to be tried and debugged. Name might be subject to change
# in the near future.
try-runtime = ["node-template-runtime/try-runtime", "try-runtime-cli/try-runtime"]
13 changes: 13 additions & 0 deletions node/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,19 @@ pub fn new_partial(
compatibility_mode: Default::default(),
})?;

// NOTE: Can be done in development mode i.e. `--dev`
// if config.offchain_worker.enabled {
// // Initialize seed for signing transaction using offchain workers. This is a convenience
// // so learners can see the transactions submitted simply running the node.
// // Typically these keys should be inserted with RPC calls to `author_insertKey`.
// sp_keystore::CryptoStore::sr25519_generate_new(
// &*keystore,
// node_template_runtime::pallet_ocw::KEY_TYPE,
// Some("//Alice"),
// )
// .expect("Creating key with account Alice should succeed.");
// }

Ok(sc_service::PartialComponents {
client,
backend,
Expand Down
5 changes: 3 additions & 2 deletions pallets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ Pallets are the building blocks of the runtime. They are the modules that implem
### Real

- [x] [Bank](./bank/) - A pallet to to handle multiple investment types.
- [ ] 🧑🏻‍💻 DPoS Substrate node
- [ ] AntelopeAccount
- [ ] 🧑🏻‍💻 EOSIO System
- [ ] Antelope Name
- [ ] Antelope Account
<details>
<summary>View details:</summary>
Q. In Rust substrate, I really think that account generation may have a better way. As in, in substrate, currently account has this stash versus controller model. And I feel that it should be in such a way where an account has two key pairs. So if one of the key pair is compromised, the person can actually use the other key pair to change that key pair. Can we do that?
Expand Down
1 change: 1 addition & 0 deletions pallets/bank/CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file.
the IS formula.

- [ ] Added a RD vault for opening a RD account/vault.
- [ ] Add OCW (Off-chain worker) for setting the FD interest rate based on repo_rate & inflation fetched externally.
- [ ] We can also add the functionality of auto_maturity of FDs using hooks.
- [ ] After every few blocks, some balance is transferred to the TREASURY account.
- L0 chain's inflation is transferred to the TREASURY account.
Expand Down
91 changes: 56 additions & 35 deletions pallets/ocw/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
//! Offchain tutorial source: https://docs.substrate.io/tutorials/build-application-logic/add-offchain-workers/

#![cfg_attr(not(feature = "std"), no_std)]
use frame_support::sp_runtime::traits::BlockNumberProvider;
use frame_support::sp_runtime::traits::Saturating;
use frame_support::traits::Get;
use frame_system::offchain::{
AppCrypto, CreateSignedTransaction, SendSignedTransaction, SendUnsignedTransaction,
SignedPayload, Signer, SigningTypes, SubmitTransaction,
};

use sp_core::crypto::KeyTypeId;
// use sp_std::vec::Vec;

Expand Down Expand Up @@ -52,6 +54,7 @@ pub use pallet::*;
pub mod pallet {
use super::*;
use frame_support::{log, pallet_prelude::*};

use frame_system::pallet_prelude::*;

#[pallet::pallet]
Expand All @@ -64,6 +67,10 @@ pub mod pallet {
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;

type AuthorityId: AppCrypto<Self::Public, Self::Signature>;

/// Maximum number of prices.
#[pallet::constant]
type MaxPrices: Get<u32>;
}

#[pallet::hooks]
Expand All @@ -90,7 +97,7 @@ pub mod pallet {
// - `Some((account, Ok(())))`: transaction is successfully sent
// - `Some((account, Err(())))`: error occurred when sending the transaction
let results =
signer.send_signed_transaction(|_account| Call::do_something { something: 42 });
signer.send_signed_transaction(|_account| Call::submit_price { price: 42 });

for (acc, res) in &results {
match res {
Expand All @@ -102,22 +109,17 @@ pub mod pallet {
// ...
}

// The pallet's runtime storage items.
// https://docs.substrate.io/main-docs/build/runtime-storage/
#[pallet::storage]
#[pallet::getter(fn something)]
// Learn more about declaring storage items:
// https://docs.substrate.io/main-docs/build/runtime-storage/#declaring-storage-items
pub type Something<T> = StorageValue<_, u32>;
pub type Prices<T: Config> = StorageValue<_, BoundedVec<u32, T::MaxPrices>, ValueQuery>;

// Pallets use events to inform users when important changes are made.
// https://docs.substrate.io/main-docs/build/events-errors/
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
/// Event documentation should end with an array that provides descriptive names for event
/// parameters. [something, who]
SomethingStored { something: u32, who: T::AccountId },
/// New price added
NewPrice { price: u32, who_maybe: Option<T::AccountId> },
}

// Errors inform users that something went wrong.
Expand All @@ -127,6 +129,8 @@ pub mod pallet {
NoneValue,
/// Errors should have helpful documentation associated with them.
StorageOverflow,
/// error in calculating avg price
AvgPriceCalculationError,
}

// Dispatchable functions allows users to interact with the pallet and invoke state changes.
Expand All @@ -138,39 +142,56 @@ pub mod pallet {
/// storage and emits an event. This function must be dispatched by a signed extrinsic.
#[pallet::call_index(0)]
#[pallet::weight({10_000})]
pub fn do_something(origin: OriginFor<T>, something: u32) -> DispatchResult {
// Check that the extrinsic was signed and get the signer.
// This function will return an error if the extrinsic is not signed.
// https://docs.substrate.io/main-docs/build/origins/
pub fn submit_price(origin: OriginFor<T>, price: u32) -> DispatchResult {
let who = ensure_signed(origin)?;

// Update storage.
<Something<T>>::put(something);
Self::add_price(Some(who), price);

// Emit an event.
Self::deposit_event(Event::SomethingStored { something, who });
// Return a successful DispatchResultWithPostInfo
Ok(())
}
}

/// An example dispatchable that may throw a custom error.
#[pallet::call_index(1)]
#[pallet::weight({10_000})]
pub fn cause_error(origin: OriginFor<T>) -> DispatchResult {
let _who = ensure_signed(origin)?;

// Read a value from storage.
match <Something<T>>::get() {
// Return an error if the value has not been set.
None => return Err(Error::<T>::NoneValue.into()),
Some(old) => {
// Increment the value read from storage; will error in the event of overflow.
let new = old.checked_add(1).ok_or(Error::<T>::StorageOverflow)?;
// Update the value in storage with the incremented result.
<Something<T>>::put(new);
Ok(())
},
impl<T: Config> BlockNumberProvider for Pallet<T> {
type BlockNumber = T::BlockNumber;

fn current_block_number() -> Self::BlockNumber {
<frame_system::Pallet<T>>::block_number()
}
}
}

enum TransactionType {
Signed,
UnsignedForAny,
UnsignedForAll,
Raw,
None,
}

impl<T: Config> Pallet<T> {
fn add_price(who_maybe: Option<T::AccountId>, price: u32) {
frame_support::log::info!("Adding price: {}", price);
// update the price, calcualate the average.
<Prices<T>>::mutate(|prices| {
if prices.try_push(price).is_err() {
prices[(price % T::MaxPrices::get()) as usize] = price;
}
});

let avg_price = Self::average_price().expect("error in Calculation of avg price");
frame_support::log::info!("Average price: {}", avg_price);

// Emit an event.
Self::deposit_event(Event::NewPrice { price, who_maybe });
}

fn average_price() -> Option<u32> {
let prices = <Prices<T>>::get();
if prices.is_empty() {
None
} else {
Some(prices.iter().fold(0, |acc, x| acc.saturating_add(*x) / prices.len() as u32))
}
}
}
4 changes: 4 additions & 0 deletions runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ pallet-lockable-currency = { version = "0.1.0", default-features = false, path =
pallet-bank = { version = "0.1.4", default-features = false, path = "../pallets/bank" }
pallet-arithmetic = { version = "0.1.0", default-features = false, path = "../pallets/arithmetic" }
pallet-eosio-system = { version = "0.1.0", default-features = false, path = "../pallets/eosio_system" }
pallet-ocw = { version = "0.1.0", default-features = false, path = "../pallets/ocw" }

[build-dependencies]
substrate-wasm-builder = { version = "5.0.0-dev", git = "https://github.com/paritytech/substrate.git", optional = true , branch = "polkadot-v0.9.42" }
Expand Down Expand Up @@ -89,6 +90,7 @@ std = [
"pallet-bank/std",
"pallet-arithmetic/std",
"pallet-eosio-system/std",
"pallet-ocw/std",
"pallet-timestamp/std",
"pallet-transaction-payment-rpc-runtime-api/std",
"pallet-transaction-payment/std",
Expand Down Expand Up @@ -123,6 +125,7 @@ runtime-benchmarks = [
"pallet-bank/runtime-benchmarks",
"pallet-arithmetic/runtime-benchmarks",
"pallet-eosio-system/runtime-benchmarks",
"pallet-ocw/runtime-benchmarks",
"pallet-timestamp/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
]
Expand All @@ -145,6 +148,7 @@ try-runtime = [
"pallet-bank/try-runtime",
"pallet-arithmetic/try-runtime",
"pallet-eosio-system/try-runtime",
"pallet-ocw/try-runtime",
"pallet-timestamp/try-runtime",
"pallet-transaction-payment/try-runtime",
]
76 changes: 73 additions & 3 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::{
AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, NumberFor, One, Verify,
AccountIdLookup, BlakeTwo256, Block as BlockT, Extrinsic, IdentifyAccount, NumberFor, One,
Verify,
},
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult, MultiSignature,
Expand Down Expand Up @@ -69,9 +70,12 @@ pub use pallet_lockable_currency;
/// Import the arithmetic pallet.
pub use pallet_arithmetic;

/// Import the dpos pallet.
/// Import the eosio_system pallet.
pub use pallet_eosio_system;

/// Import the ocw pallet.
pub use pallet_ocw;

/// An index to a block.
pub type BlockNumber = u32;

Expand Down Expand Up @@ -386,6 +390,70 @@ impl pallet_eosio_system::Config for Runtime {
type MaxProducerInfoUrlLen = MaxProducerInfoUrlLen;
}

/// Configure the pallet-ocw in pallets/ocw.
impl pallet_ocw::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type AuthorityId = pallet_ocw::crypto::TestAuthId;
}

use codec::Encode;
use sp_runtime::{generic::Era, SaturatedConversion};

impl<LocalCall> frame_system::offchain::CreateSignedTransaction<LocalCall> for Runtime
where
RuntimeCall: From<LocalCall>,
{
fn create_transaction<C: frame_system::offchain::AppCrypto<Self::Public, Self::Signature>>(
call: RuntimeCall,
public: <Signature as Verify>::Signer,
account: AccountId,
nonce: Index,
) -> Option<(RuntimeCall, <UncheckedExtrinsic as Extrinsic>::SignaturePayload)> {
let tip = 0;
// take the biggest period possible.
let period =
BlockHashCount::get().checked_next_power_of_two().map(|c| c / 2).unwrap_or(2) as u64;
let current_block = System::block_number()
.saturated_into::<u64>()
// The `System::block_number` is initialized with `n+1`,
// so the actual block number is `n`.
.saturating_sub(1);
let era = Era::mortal(period, current_block);
let extra = (
frame_system::CheckNonZeroSender::<Runtime>::new(),
frame_system::CheckSpecVersion::<Runtime>::new(),
frame_system::CheckTxVersion::<Runtime>::new(),
frame_system::CheckGenesis::<Runtime>::new(),
frame_system::CheckEra::<Runtime>::from(era),
frame_system::CheckNonce::<Runtime>::from(nonce),
frame_system::CheckWeight::<Runtime>::new(),
pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(tip),
);
let raw_payload = SignedPayload::new(call, extra)
.map_err(|e| {
frame_support::log::warn!("Unable to create signed payload: {:?}", e);
})
.ok()?;
let signature = raw_payload.using_encoded(|payload| C::sign(payload, public))?;
let address = account;
let (call, extra, _) = raw_payload.deconstruct();
Some((call, (sp_runtime::MultiAddress::Id(address), signature, extra)))
}
}

impl frame_system::offchain::SigningTypes for Runtime {
type Public = <Signature as Verify>::Signer;
type Signature = Signature;
}

impl<C> frame_system::offchain::SendTransactionTypes<C> for Runtime
where
RuntimeCall: From<C>,
{
type Extrinsic = UncheckedExtrinsic;
type OverarchingCall = RuntimeCall;
}

// Create the runtime by composing the FRAME pallets that were previously configured.
construct_runtime!(
pub struct Runtime
Expand All @@ -411,6 +479,7 @@ construct_runtime!(
Bank: pallet_bank,
Arithmetic: pallet_arithmetic,
EOSIOSystem: pallet_eosio_system,
OCW: pallet_ocw,
}
);

Expand Down Expand Up @@ -465,7 +534,8 @@ mod benches {
[pallet_lockable_currency, LockableCurrency]
[pallet_bank, Bank]
[pallet_arithmetic, Arithmetic]
[pallet_eosio_system, DPoS]
[pallet_eosio_system, EOSIOSystem]
[pallet_ocw, OCW]
);
}

Expand Down

0 comments on commit fb17c5f

Please sign in to comment.