GithubHelp home page GithubHelp logo

deeper-chain / deeper-chain Goto Github PK

View Code? Open in Web Editor NEW
137.0 26.0 58.0 55.35 MB

deeper chain is the blockchain layer for deeper network.

License: Apache License 2.0

Rust 94.75% JavaScript 4.84% Handlebars 0.32% Solidity 0.10%

deeper-chain's Introduction

Deeper-chain: A Comprehensive Guide

Build Codecov

1. Introduction

Background

Deeper-chain is a groundbreaking blockchain platform that aims to redefine the landscape of decentralized networks. Built on the robust Substrate framework, it offers a secure, scalable, and efficient environment for decentralized applications (dApps) and smart contracts. This platform is not just another blockchain; it is the cornerstone of a new era in blockchain technology. It brings a plethora of features that are geared towards enhancing user experience, developer flexibility, and overall network performance.

Objectives

The primary objectives of Deeper-chain are multi-faceted:

  1. Security: To provide a secure and tamper-proof system that can withstand various types of attacks.
  2. High Throughput: To ensure high throughput so that transactions are processed quickly.
  3. Low Latency: To maintain low latency for real-time applications.
  4. Interoperability: To facilitate seamless interoperability between different blockchain networks.
  5. Community Governance: To offer a robust governance model that allows for community-driven updates and changes.

Scope

This document serves as a comprehensive guide for developers, node operators, and community members. It aims to be the go-to resource for anyone interested in understanding, installing, and contributing to Deeper-chain. It covers everything from the basic features to advanced modules and integration points.

Terminology

  • Node: A computer connected to the Deeper-chain network that participates in network activities.
  • Validator: A specialized node that participates in the consensus algorithm to validate transactions and create new blocks.
  • Nominator: A token holder who nominates a validator to act on their behalf.
  • Governance: The system by which decisions are made within the network, often involving proposals and voting mechanisms.

2. Features of Deeper-chain

2.1 Security Measures

Deeper-chain employs a multi-layered security architecture that includes advanced cryptographic techniques, a robust consensus algorithm, and additional mechanisms to guard against malicious activities. Features such as Runtime Verification and Off-chain Workers contribute to the overall security of the network. The platform also employs various other security measures like two-factor authentication, cold storage options for assets, and regular security audits.

2.2 Scalability Solutions

Deeper-chain addresses the challenges of scalability by employing a range of solutions. It utilizes sharding technology alongside parallel transaction processing, which ensures that the network can handle a large number of transactions without compromising on speed or efficiency. The platform also employs various layer-2 solutions like state channels and rollups to further enhance its scalability.

2.3 Efficiency Metrics

Deeper-chain is designed to be an energy-efficient blockchain. It employs mechanisms like Proof-of-Stake (PoS) and other consensus algorithms that require less computational power, thereby reducing the overall energy consumption. The platform also focuses on optimizing code and reducing computational complexity wherever possible.

2.4 Interoperability

Interoperability is one of the standout features of Deeper-chain. Built on the Substrate framework, it is inherently compatible with other blockchains in the Polkadot ecosystem. This allows for seamless asset and data transfer across different networks. The platform also supports various cross-chain communication protocols to facilitate interaction with blockchains outside the Polkadot ecosystem.

2.5 Governance Model

Deeper-chain adopts a community-driven governance model. It empowers its users to propose changes and vote on them. This democratic approach ensures that the network evolves in a way that benefits its entire ecosystem. The governance model is designed to be transparent, inclusive, and fair, allowing for a wide range of proposals to be considered and implemented.

3. Prerequisites

3.1 Software Requirements

  • Rust v1.50.0 or above: The Rust programming language is essential for compiling and running the Deeper-chain node.
  • Substrate v2.0.0 or above: Substrate is the framework upon which Deeper-chain is built. It provides the basic building blocks for creating a blockchain.
  • Node.js v14.0.0 or above: Node.js is required for running various scripts and tasks.
  • Yarn package manager: Yarn is used for managing Node.js packages.

3.2 Hardware Requirements

  • A minimum of 8 GB RAM: Adequate memory is essential for smooth operation.
  • At least 500 GB of free disk space: Sufficient storage is necessary for holding the blockchain data.
  • A stable internet connection: A reliable internet connection is crucial for staying synced with the network.

4. Installation and Setup

4.1 Environment Configuration

Before you begin the installation process, you need to set up the environment variables. This involves configuring the Rust toolchain, setting up the PATH variables, and installing the required Node.js packages.

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME

/.cargo/env

4.2 Building from Source

To build Deeper-chain from source, you'll need to clone the repository and compile the code. This can be done using the following commands:

git clone https://github.com/Deeper-chain/Deeper-chain.git
cd Deeper-chain
cargo build --release

4.3 Running a Node

After successfully building from source, you can run a Deeper-chain node using the following command:

./target/release/deeper-chain --dev

4.4 Single Node Development Chain

Purge any existing dev chain state:

./target/release/deeper-chain purge-chain --dev

Start a dev chain:

./target/release/deeper-chain --dev

Or, start a dev chain with detailed logging:

RUST_LOG=debug RUST_BACKTRACE=1 ./target/release/deeper-chain -lruntime=debug --dev

4.5 Multi-Node Local Testnet

If you want to see the multi-node consensus algorithm in action, refer to our Start a Private Network tutorial.

This will start a development node on your local machine. For running a node in a production environment, additional flags and configurations are required.

5. Update weights.rs in pallet

5.1 Build deeper-chain with --features runtime-benchmarks

cd cli/
cargo build --release --features runtime-benchmarks

5.2 Run shell command to update weights.rs

./target/release/deeper-chain benchmark pallet \
--chain=dev \
--steps=50 \
--repeat=20 \
--pallet=pallet_staking \
--extrinsic='*' \
--execution=wasm \
--wasm-execution=compiled \
--heap-pages=4096 \
--output=./pallets/staking/src/weights.rs \
--template=./.maintain/frame-weight-template.hbs 

6. Network Architecture

6.1 Node Types

Deeper-chain supports various types of nodes, each serving a specific function within the network:

  1. Full Nodes: These nodes store the entire blockchain data and validate all transactions. They are the backbone of the network, ensuring data integrity and serving as a relay for transactions.

  2. Validator Nodes: These are specialized full nodes that participate in the consensus algorithm. They validate transactions, create new blocks, and are responsible for the overall security of the network. Validators are chosen based on a combination of factors including stake, uptime, and reputation.

  3. Light Nodes: These nodes do not store the entire blockchain but can still validate transactions and blocks. They are optimized for low-resource environments and are ideal for mobile applications and IoT devices.

6.2 Consensus Mechanism

Deeper-chain employs a hybrid consensus mechanism that combines elements of Proof-of-Stake (PoS) and Byzantine Fault Tolerance (BFT). This ensures a high level of security while maintaining efficiency and scalability. Validators are chosen based on the amount of stake they hold, and they participate in the consensus process to validate transactions and produce new blocks.

6.3 Network Topology

The network architecture of Deeper-chain is designed to be modular and flexible. It consists of various layers, including the core blockchain layer, the consensus layer, and the application layer. Each layer is designed to be interchangeable, allowing for easy upgrades and modifications.

7. Smart Contracts and dApps

7.1 Smart Contract Development

Deeper-chain provides a rich environment for developing smart contracts. It supports multiple programming languages, including Solidity and Rust, and offers a range of pre-built modules for common functionalities. Developers can also make use of the extensive documentation and tutorials available to get started with smart contract development.

7.2 DApp Ecosystem

Deeper-chain supports dApps in various sectors including finance, advertising, oracles, and the Internet. The platform provides a rich set of tools and SDKs to facilitate dApp development. With its robust features and high-performance metrics, Deeper-chain aims to be the go-to platform for dApp development. It offers various tools and SDKs to facilitate the development process, making it easier for developers to bring their ideas to life.

8. Wallet Integration

8.1 Web Wallet

Deeper-chain supports web-based wallets that offer a user-friendly interface for managing your assets. These wallets are secured with advanced cryptographic techniques to ensure the safety of your funds. They also offer features like multi-signature support, transaction history, and more.

8.2 Hardware Wallet

Deeper-chain has developed its own hardware wallet, designed to securely store various digital assets. These physical devices offer an extra layer of protection, safeguarding your assets from online threats. They are compatible with most major hardware wallet brands and offer a straightforward setup process.

9. Development Guidelines

9.1 Code Review Process

All code contributions to Deeper-chain go through a rigorous review process. This involves automated testing, manual review by core developers, and a final approval from the governance committee. The platform employs Continuous Integration (CI) and Continuous Deployment (CD) practices to ensure that all code changes are automatically tested and deployed.

9.2 Benchmarking and Weight Calculation

Performance is a key focus in Deeper-chain development. All new features and updates must undergo benchmarking to assess their impact on network performance. Weight calculations are also performed to ensure that the network remains balanced and efficient. Various performance metrics are monitored, including transaction speed, block time, and resource utilization.

10. Contributing to Deeper-chain

10.1 Code Contributions

Developers are encouraged to contribute to Deeper-chain by submitting pull requests. Detailed guidelines for code contributions can be found in the CONTRIBUTING.md file. The platform also offers a bug bounty program to incentivize the discovery and reporting of security vulnerabilities.

10.2 Documentation Updates

Updates to documentation are equally important. Whether it's fixing typos or adding new sections, all contributions are welcome. The platform maintains a separate repository for documentation, and contributions can be made through pull requests.

10.3 Community Engagement

Community involvement is crucial for the growth and success of Deeper-chain. Users can participate in governance, propose new features, and engage in discussions to shape the future of the network. Various community channels like forums, social media, and chat rooms are available for users to connect and collaborate.

11. License and Compliance

Deeper-chain is released under the MIT License, ensuring that it remains open-source and accessible to all. Compliance with legal and regulatory standards is of utmost importance, and users are advised to read the LICENSE.md file for more details. The platform also undergoes regular audits to ensure compliance with data protection and financial regulations.

deeper-chain's People

Contributors

amadeusgb avatar baidang201 avatar chaosma avatar clivia-hy avatar deeper-zjin avatar donilan avatar donileongdeepernetwork avatar fyang1024 avatar geb789 avatar jerry-yu avatar kzjin avatar lbcbcbc avatar lzw65 avatar orangelovegithub avatar shiyivei avatar songhaoxin avatar todaylab avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

deeper-chain's Issues

feedback about DPN equipments

1.Hope to provide a complete interface to every device, even if not mining.The system calculates credit points in a timely manner, improves the enthusiasm of users to connect to the Internet, and promotes the online rate of equipment.

2.Mining is upgraded again, intelligent mining, simply turn on the mining switch, automatically register and start queuing, automatically mine after the credit score reaches the standard, when there are multiple devices, you can merge the wallet address on the interface, I hope the mnemonic words can be very good processing. I have no mining experience, please forgive me if I am wrong.

3.The firmware download address provides a test version, which is convenient for users who are willing to test to download and install.

Thank you!

remove `inspect` command

The inspect command can be used to decode a block or extrinsic, but it's not very useful, because

  1. local db must contains this block
  2. only works when native runtime versions match

The recommend way to inspect should be through https://apps.deeper.network/, so I think it's ok to remove inspect directory.

move to rust edition 2021

Substrate version v0.9.13 already support edition 2021, I think we should keep up with it and may get more benefits.

Optimize credit rating model

Now, we have a problem. The current credit is divided into 9 levels, but if the user's credit score is at the boundary value, one point deduction will change one level, and the range of one level is 100. At the same time, it is very difficult to increase the credit score by 1 point, which will cause the user experience not good.
There are several options:

  1. Raise a small credit score for all users uniformly, which can temporarily avoid users' poor experience, such as:

const user_extra_credit = 10;

Advantages: small changes, easy to test; disadvantages: not the best method;
2. Modify the credit rating function and calculate the pledge reward according to the actual credit score;
Benefits: It can avoid the pledge award level complaints caused by the credit rating range;
Disadvantages: There are major changes in many codes, which require a lot of testing and increase the amount of calculation.

Burn DPR to recover the decreased credit

Summary

The deeper devices must repeatedly submit ImOnline to keep the heartbeats with a deeper chain.
However, the device may accidentally fail to submit the heartbeat, which leads to the decrease of the credit.

Motivation

To avoid such consequences, we proposed to purchase the credit with DPR.
Users should be able to recover their credit lost if they will.
But the amount of credit cannot exceed the highest credit of the user before.

Design

In the design, we simply added a method in the credit pallet.
The DPRs consumed for the credits are sent to the treasury module (account).

The price for the credit purchased needs to be discussed within the community.
Once the price is adjusted well until we see a pattern, we could automate it in the future version.

DIP-1:Easy Cent (EZC) Trading Medium Criterion

Easy Cent (EZC) Trading Medium Criterion

Overview:

EZC(Easy Cent) stablecoin: A kind of on-chain point, converted from DPR, it has non-transferable and non-tradable characteristics. Buying or using EZC is not investment and can pass the SEC's Howey test. Therefore, it can be purchased by any payment methods, such as Credit card, Paypal, Apple store, etc.

Motivation:

To provide a medium of exchange for payment application and service fee on Deeper chain to pay for applications and services, which allows to promote the use of on-chain applications at a stable and predictable price.

Stakeholders:

Developers and users of various applications using the EVM platform

Principle Description:

Issue a type of stable coin EZC, its exchange rate will be anchored in US dollars (1 EZC = 0.01 USD), through the credit card to be able to conveniently buy stable coins, but also by burning DPR to get the corresponding stable coins, but the DPR exchange rate is floating, according to the DPR market price to adjust the number of EZC exchange.

Detailed design:

1. Fiat currency exchange mechanism.

Buying EZC with a credit card will trigger the mint() method to generate the equivalent amount of EZC into the user's address.

2. Burning exchange mechanism.

The DPR market price is Dynamically obtained through the oracle machine model to get data from multiple nodes. It will start with BFT voting, weighted average, and then blockchain will exchange the corresponding stable coin based on DPR/USD price.

3. Application incentive mechanism.

  • Paying DApp transaction fees through stable coins, which will be deducted directly.
  • If the EZC balance is insufficient, priority will be given to automatically burning DPR to obtain the equivalent amount of EZC for payment, and if DPR is insufficient, the user will be reminded that the transaction cannot be made.
  • The system will generate equal DPR rewards, and the node providing Server will receive DPR rewards from the system immediately, and the final reward depends on the number of nodes sharing DPR rewards.

4. Restrictions.

  • EZC is not transferable.
  • Cannot be reverse converted to fiat currency.
  • EZC exchange limit of 100,000 EZC per account.

Engineering Difficulties and Workload:

Difficulties: issuing EZC stablecoins and how to ensure interaction with DPR issues.

  • issuing EZC stable coins, about 1 day.
  • completing EZC interaction with DPR, about 1~2 weeks.
  • completing the prophecy machine feeding and intermodulation, about 1~2 weeks.

Disadvantages:

Need to manage and pair-bind both Deeper and EVM addresses when users use DPR burning to obtain EZCs.

Blockchain file storage over Deeper chain

File storage is a fundamental application for web3. This proposal is to build the files storage system over the blockchain.
Users can spend DPR to store their files. Beyond that, more applications can be feasible with blockchain storage.

The miner and the market decide the storage price.
The blockchain will set up a storage contract. Compared to a smart contract, the storage contract requires periodic verification.

Problem

On a permission-less storage network, the storage providers may play out-souring attacks, which is risky to the file storage safety. The periodic verification requires performing the Proof of Replication to ensure the miners spend dedicated storage resources for the file owner. The random information from the blockchain can be used as a challenge to the miners. The miner must respond to the challenge to convince the owner.

Solution

Currently, we are working on designing the storage contract prototype. It will involve the new protocol and algorithm to prevent out-souring attacks. The verification protocol may require more zero-knowledge magic.

The storage contract will keep the information about the files to save on the blockchain. The files were encrypted before uploading to the decentralized storage system. The encrypted data is divided into small chunks. Next, the chunks will be replicated into the unique replication form. Finally, the verification would start once the contract is initialized.

The design is early in the draft, so we may change the design detail or break the task into small components. Since the periodic verification would consume more TPS, it depends on better blockchain performance to support our application.

deeper-chain got crashed with error messages

Aug 31 17:23:13 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]: 2021-08-31 17:23:13  💤 Idle (9 peers), best: #57062 (0x3edc…f108), finalized #57060 (0xbf09…0611), ⬇ 10.9kiB/s ⬆ 10.2kiB/s
Aug 31 17:23:15 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]: 2021-08-31 17:23:15  ✨ Imported #57063 (0x8c47…0903)
Aug 31 17:23:18 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]: 2021-08-31 17:23:18  💤 Idle (9 peers), best: #57063 (0x8c47…0903), finalized #57061 (0x797f…5f0d), ⬇ 13.8kiB/s ⬆ 11.6kiB/s
Aug 31 17:23:20 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]: 2021-08-31 17:23:20  🙌 Starting consensus session on top of parent 0x8c47f12cd58c88e0a2964c68ff378c88905f0c76def1f9f6e89ed976aa620903
Aug 31 17:23:20 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]: 2021-08-31 17:23:20  🎁 Prepared block for proposing at 57064 [hash: 0xb3a58cb878f4713ec3712a9ae329e1e0cc81b24c5e59358ec5e9b807e0951bf0; parent_hash: 0x8c47…0903; extrinsics (1): [0xf399…ac7a]]
Aug 31 17:23:20 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]: 2021-08-31 17:23:20  🔖 Pre-sealed block for proposal at 57064. Hash now 0xc06b2aeb6ffd1e6d5c78a95a28634c9226098583348fc1f99490f4c4b59066e4, previously 0xb3a58cb878f4713ec3712a9ae329e1e0cc81b24c5e59358ec5e9b807e0951bf0.
Aug 31 17:23:20 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]: 2021-08-31 17:23:20  ✨ Imported #57064 (0xc06b…66e4)
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]: ====================
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]: Version: 2.0.0-28811e7-x86_64-linux-gnu
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:    0: sp_panic_handler::set::{{closure}}
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:    1: std::panicking::rust_panic_with_hook
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:              at /rustc/f98721f886ab52d32d622ad0a46216ad03f3e525/library/std/src/panicking.rs:595:17
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:    2: std::panicking::begin_panic::{{closure}}
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:    3: std::sys_common::backtrace::__rust_end_short_backtrace
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:    4: std::panicking::begin_panic
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:    5: <libp2p_swarm::toggle::ToggleProtoHandler<TInner> as libp2p_swarm::protocols_handler::ProtocolsHandler>::inject_listen_upgrade_error
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:    6: <libp2p_swarm::protocols_handler::select::ProtocolsHandlerSelect<TProto1,TProto2> as libp2p_swarm::protocols_handler::ProtocolsHandler>::inject_listen_upgrade_error
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:    7: <libp2p_swarm::protocols_handler::node_handler::NodeHandlerWrapper<TProtoHandler> as libp2p_core::connection::handler::ConnectionHandler>::poll
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:    8: libp2p_core::connection::Connection<TMuxer,THandler>::poll
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:    9: <libp2p_core::connection::manager::task::Task<F,M,H,I,O,E> as core::future::future::Future>::poll
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   10: <sc_service::task_manager::prometheus_future::PrometheusFuture<T> as core::future::future::Future>::poll
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   11: <futures_util::future::select::Select<A,B> as core::future::future::Future>::poll
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   12: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   13: <tracing_futures::Instrumented<T> as core::future::future::Future>::poll
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   14: <sc_service::task_manager::WithTelemetrySpan<T> as core::future::future::Future>::poll
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   15: tokio::runtime::task::core::Core<T,S>::poll
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   16: <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   17: tokio::runtime::task::harness::Harness<T,S>::poll
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   18: std::thread::local::LocalKey<T>::with
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   19: tokio::runtime::thread_pool::worker::Context::run_task
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   20: tokio::runtime::thread_pool::worker::Context::run
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   21: tokio::macros::scoped_tls::ScopedKey<T>::set
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   22: tokio::runtime::thread_pool::worker::run
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   23: tokio::loom::std::unsafe_cell::UnsafeCell<T>::with_mut
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   24: <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   25: tokio::runtime::task::raw::poll
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   26: tokio::runtime::blocking::pool::Inner::run
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   27: tokio::runtime::context::enter
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   28: std::sys_common::backtrace::__rust_begin_short_backtrace
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   29: core::ops::function::FnOnce::call_once{{vtable.shim}}
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   30: <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:              at /rustc/f98721f886ab52d32d622ad0a46216ad03f3e525/library/alloc/src/boxed.rs:1546:9
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:       <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:              at /rustc/f98721f886ab52d32d622ad0a46216ad03f3e525/library/alloc/src/boxed.rs:1546:9
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:       std::sys::unix::thread::Thread::new::thread_start
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:              at /rustc/f98721f886ab52d32d622ad0a46216ad03f3e525/library/std/src/sys/unix/thread.rs:71:17
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   31: start_thread
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:   32: clone
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]: Thread 'tokio-runtime-worker' panicked at 'Unexpected Either::Right on enabled `inject_listen_upgrade_error`.', /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/libp2p-swarm-0.27.1/src/toggle.rs:288
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]: This is a bug. Please report it at:
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network deeper-chain[38377]:         https://github.com/paritytech/substrate/issues/new
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network systemd[1]: deeper-chain.service: Main process exited, code=exited, status=1/FAILURE
Aug 31 17:23:22 ap-east-1-001-mainnet-chain.deeper.network systemd[1]: deeper-chain.service: Failed with result 'exit-code'.
Aug 31 17:23:27 ap-east-1-001-mainnet-chain.deeper.network systemd[1]: deeper-chain.service: Scheduled restart job, restart counter is at 1.

Charge some fee in micropayment

Currently, micropayment transactions just cost a little weight fee as other transactions, but people can get a lot of reward from micropayment. So, I suggest we charge some additional fee in micropayment like income tax. These tax goes into treasury and can be used to inspire community members.

micropayment occupy too much DPR

Problem

After staking 1000 DPR through ethereum contract, many people can't get reword.

Analysis

After staking 1000 DPR, people got 2 DPR in their account, if they use DPN, then micropayment will consume these 2 DPR by calling open_channel and add_balance, if the user's balance is below 1 DPR, this account will be dust killed.

Plan

To prevent micropayment from making an account's balance lower than 1 DPR, we should add more validation on open_channel and add_channel.

I'd like to work on this issue.

Add credit to client when it consumed enough traffic

Summary

A client connect to a server and consumed the server's traffic, the client should get credit reward.

Motivation

Currently the only way a device can get credit reward is to perform as a server and share its traffic with other device. But because many devices lack of an public IP address, so it can't become a server. Devices without public IP also help deeper chain safer, they should also have the right to get PoCr rewards.

Detailed design

image

  1. Share criterion: traffic shared in the last 2 days is greater than 10M.
  2. Consume criterion: traffic consumed in the last 2 days is greater than 100M.

Statistics gathered

lack.

Simplify chain_spec.rs

campaign_0_user_credit_data, campaign_0_user_accounts ... seems not using.
I checked several addresses in mainnet and testnet

and found their credit and balance have no value
image

I think we can remove fir | flaming-fir, staging from chain spec to avoid confusing.

The deduction of credit score may not be recorded in the history.

When the credit score deduction and credit rating update are on the same day(Because the number of blocks in the same day corresponds to equal era), the credit score deduction record in user_credit_history will be overwritten by the credit rating update record!

Reward nothing in all subsequent campaign when 1st participated in is over.

Problem Statement

When an account ends after the first stacking campaign it participated in, it will not receive any benefits if it participates in any campaign after that date.
This phenomenon is caused by the following snippet in get_reward() under credit/src/lib.rs.

...
565 let onboard_era = credit_history[0].0;
566 let expiry_era = onboard_era + credit_data.reward_eras - 1;
567 if from > expiry_era {
568     return (None, weight);
569 }
570 
571 let credit_map = Self::get_credit_map(credit_history, from, cmp::min(to, expiry_era));

...

onboard_era: The point in time when the account first participated in the campaign.
reward_eras: The fixed length of the first campaign the account participated in.
from: The point in time at which the account was last settled and from which earnings will be re-stated.

Since 'from' grows dynamically and 'expiry_era' is relatively fixed, after the first campaign is over, when the other campaign are settled for revenue, it causes the 567 lines of code to be constant true and the account does not receive any revenue.

Conclusion: The fact that 'expiry_era' does not accurately reflect the last end point of the campaign an account is involved in is the root cause of this problem.

Solutions

This problem can be solved by finding a way to dynamically capture the latest end point of a given account's stacking campaign at the settlement point.Based on this, there are two possible solutions to this problem.
Special Note: There are usually two types of campaign, one with a fixed end point and the other without a fixed end point but with a fixed campaign period. The solutions discussed in this article are based on the latter.

Solution 1 :Add a new method

Ideas for solution

From the logic of the subsequent code to calculate the specific return, line 571 calls the get_credit_map(credit_history,from,to) method , which takes a list of discrete historical credit data for the account at each point in time, accumulates them into specific durations, and then calculates the return separately. Similarly, we can also calculate the latest campaign expiration point of the account based on this list of historical credit data.

For example, the credit history of Account A at the time of settlement is as follows.

credit_history =
[
  [
    3,
    {
      campaign_id: 2,
      credit: 110,
      ...
      reward_eras: 270
    }
  ],

  [
    7,
    {
      campaign_id: 2,
      credit: 111,
      ...
      reward_eras: 270
    }
  ],

  [
    9,
    {
      campaign_id: 3,
      credit: 100,
      ...
      reward_eras: 170
    }
  ]
]

Obviously, the latest expiration time point of the campaign for account A is: 273 era (i.e. the end time point of the campaign campaign_id of 2).
(campaign_id2 endpoint = 3+270) > (campaign_id3 endpoint = 9+170)

Implementation

  1. Define and implement methods
        /// get the latest campaign expiration point of the account.
    pub fn get_expiry_era(credit_history: &Vec<(EraIndex, CreditData)) -> EraIndex {
           if credit_history.is_empty() {
              return 0;
      }

    let mut expiry_era = 0;
    let mut campaign_Map = BTreeMap::<CampaignId, u16>::new();

    for (k,v)  in credit_history  {
        if !campaign_Map.contains_key(&v.campaign_id) {
            if (k + v.reward_eras) > expiry_era {
                expiry_era = k + v.reward_eras;
                campaign_Map.insert(v.campaign_id.clone(), 1);
            } 
        }
    }

    expiry_era
}
  1. Change the original problem code to the following:
...
565 let onboard_era = credit_history[0].0; // delete this line
566 let expiry_era = Self::get_expiry_era {&credit_history) - 1;
567 if from > expiry_era
568     return (None, weight);
569 }

Advantages and Disadvantages

Advantages:
The changes are limited to this file, with controlled risk and no read or write operations to the storage, no weight overhead.

Disadvantages:
Calling the get_expiry_era() method has a traversal operation on the history records, and there are efficiency problems if there are too many records.

Solution 2 :Add a new data structure and provide setter/getter methods

Ideas for solution

Add a new data structure and serialize it into storage to hold the latest campaign end point of the account.

Implementation

  1. Add structure for storing the latest end point of the associated account campaign.
#[derive(Decode, Encode, Default, Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct CampaignErasData {
    pub campaign_id: CampaignId,
    pub start_era: EraIndex,
    pub reward_eras: EraIndex,
}

/// Information about the campaigns attended.
#[derive(Decode, Encode, Default, Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct ParticipatedCampaigns {
    pub latest_expiry_era: EraIndex,
    pub campaigns: BTreeMap<CampaignId, CampaignErasData>,
}

 /// Record information about the staking campaigns the account has participated in.
    #[pallet::storage]
    #[pallet::getter(fn participated_campaigns_info)]
    pub type ParticipatedCampaignsInfo<T: Config> =
        StorageMap<_, Blake2_128Concat, T::AccountId, ParticipatedCampaigns, OptionQuery>;
  1. Add setter method.
       /// set or refresh the latest campaign expiration point of the account.
        fn refresh_latest_expiry_eras(
            account_id: &T::AccountId,
            current_era: EraIndex,
            credit_history: &Vec<(EraIndex, CreditData)>,
            user_credit: &CreditData,
        ) -> Weight {
            let (mut participated_campaigns, ret_weight) =
                Self::fix_eras_from_history_if_needed(account_id, credit_history);
            let campaign_id = user_credit.campaign_id;
            let reward_eras = user_credit.reward_eras;

            let mut campaign_eras_data = CampaignErasData::default();
            if !participated_campaigns.campaigns.contains_key(&campaign_id) {
                campaign_eras_data.campaign_id = campaign_id;
                campaign_eras_data.start_era = current_era;
                campaign_eras_data.reward_eras = reward_eras;
                let end_era = current_era + reward_eras;
                if end_era > participated_campaigns.latest_expiry_era {
                    participated_campaigns.latest_expiry_era = end_era;
                }
            } else {
                let ori_campaign_eras_data =
                    participated_campaigns.campaigns.get(&campaign_id).unwrap();

                if ori_campaign_eras_data.reward_eras != reward_eras {
                    if ori_campaign_eras_data.reward_eras + ori_campaign_eras_data.start_era
                        < reward_eras + current_era
                    {
                        campaign_eras_data.campaign_id = ori_campaign_eras_data.campaign_id;
                        campaign_eras_data.reward_eras = reward_eras;
                        campaign_eras_data.start_era = current_era;
                        participated_campaigns.latest_expiry_era = current_era + reward_eras;
                    }
                }
            }

            participated_campaigns
                .campaigns
                .insert(campaign_id, campaign_eras_data);

            ParticipatedCampaignsInfo::<T>::mutate(&account_id, |d| match d {
                Some(campaigns_value) => *campaigns_value = participated_campaigns,
                _ => (),
            });

            let mut weight = T::DbWeight::get().reads_writes(0, 1);
            weight = weight.saturating_add(ret_weight);

            weight
        }

This method is called when a new staking campaign is attended. In the credit module, the only way to determine if a new staking campaign has been added is in the update_credit_history method.Therefore, this method is called in the update_credit_history in method to correct the latest campaign expiration point.

  1. Add getter method.
    In order to adapt to contexts in which you have previously participated in some campaigns,should add this method.
        /// get the latest campaign expiration point of the account.
        pub fn latest_expiry_era_in_campaigns(account_id: &T::AccountId) -> (EraIndex, Weight) {
            let optional_participated_campaigns: Option<ParticipatedCampaigns> =
                Self::participated_campaigns_info(account_id);
            let mut weight = T::DbWeight::get().reads_writes(1, 0);

            if !optional_participated_campaigns.is_none() {
                let latest_expiry_era = optional_participated_campaigns.unwrap().latest_expiry_era;
                if latest_expiry_era > 0 {
                    return (latest_expiry_era, weight);
                }
            }

            let credit_history = Self::user_credit_history(account_id); //  read 1
            weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 0));

            let (participated_campaigns, ret_weight) =
                Self::fix_eras_from_history(account_id, &credit_history);
            weight = weight.saturating_add(ret_weight);

            return (participated_campaigns.latest_expiry_era, weight);
        }
  1. Call refresh_latest_expiry_eras() explicitly to update the latest expiration time point when the account participates in a new campaign.

  2. Change the original problem code to the following:

...
565   let onboard_era = credit_history[0].0; //delete this line.
566   let(latest_expiry_eras,ret_weight) = Self::latest_expiry_era_in_campaigns(account_id);
567   weight = weight.saturating_add(ret_weight);
568   let expiry_era = latest_expiry_eras- 1;
569   if from > expiry_era {
570       return (None, weight);
571    }
  1. Other helper methods:
      fn fix_eras_from_history_if_needed(
            account_id: &T::AccountId,
            credit_history: &Vec<(EraIndex, CreditData)>,
        ) -> (ParticipatedCampaigns, Weight) {
            let optional_participated_campaigns: Option<ParticipatedCampaigns> =
                Self::participated_campaigns_info(account_id);
            let mut weight = T::DbWeight::get().reads_writes(1, 0);
            if !optional_participated_campaigns.is_none() {
                let participated_campaigns = optional_participated_campaigns.unwrap();
                if participated_campaigns.latest_expiry_era > 0 {
                    return (participated_campaigns, weight);
                }
            }

            let (participated_campaigns, ret_weight) =
                Self::fix_eras_from_history(account_id, credit_history);
            weight = weight.saturating_add(ret_weight);

            return (participated_campaigns, weight);
        }
    }
      fn fix_eras_from_history(
            account_id: &T::AccountId,
            credit_history: &Vec<(EraIndex, CreditData)>,
        ) -> (ParticipatedCampaigns, Weight) {
            let mut participated_campaigns: ParticipatedCampaigns =
                ParticipatedCampaigns::default();
            let mut campaigns_map: BTreeMap<CampaignId, CampaignErasData> =
                BTreeMap::<CampaignId, CampaignErasData>::new();
            for (eras, credit_data) in credit_history {
                let mut campaign_eras_data = CampaignErasData::default();
                if !campaigns_map.contains_key(&credit_data.campaign_id) {
                    campaign_eras_data.campaign_id = credit_data.campaign_id;
                    campaign_eras_data.start_era = *eras;
                    campaign_eras_data.reward_eras = credit_data.reward_eras;
                    if (campaign_eras_data.start_era + campaign_eras_data.reward_eras)
                        > participated_campaigns.latest_expiry_era
                    {
                        participated_campaigns.latest_expiry_era =
                            campaign_eras_data.start_era + campaign_eras_data.reward_eras;
                    }
                } else {
                    let ori_campaign_eras_data =
                        campaigns_map.get(&credit_data.campaign_id).unwrap();
                    if ori_campaign_eras_data.reward_eras != credit_data.reward_eras {
                        if credit_data.reward_eras + eras
                            > ori_campaign_eras_data.reward_eras + ori_campaign_eras_data.start_era
                        {
                            campaign_eras_data.campaign_id = ori_campaign_eras_data.campaign_id;
                            campaign_eras_data.reward_eras = credit_data.reward_eras;
                            campaign_eras_data.start_era = *eras;
                            participated_campaigns.latest_expiry_era =
                                credit_data.reward_eras + eras;
                        }
                    }
                }

                campaigns_map.insert(credit_data.campaign_id, campaign_eras_data);
            }

            participated_campaigns.campaigns = campaigns_map;
            ParticipatedCampaignsInfo::<T>::insert(account_id, participated_campaigns.clone());
            let mut weight = T::DbWeight::get().reads_writes(0, 1);
            weight = weight.saturating_add(T::DbWeight::get().reads_writes(0, 1));

            (participated_campaigns, weight)
        }

The main purpose of the above two methods is to repair the information on the chain that has already participated in the staking campaigns in order to calculate the correct latest end era.

Advantages and Disadvantages

Advantages:
No need to go through the list of historical credit data every time,need go through the list of historical credit data only once when call get_latest_expiry_eras at first.

Disadvantages:
a. Increased storage space, with read and write costs, will increase the weight value.
b. The set_latest_expiry_eras method needs to be called explicitly whenever a new campaign is added(In fact,this operation is no longer necessary , as it can be automatically corrected after calling get_latest_expiry_eras() ), which has a large impact.

Validation

  1. Let an account participate in the first campaign first, wait for the first campaign to end, and then participate in another campaign to see if you can get a gain.
  2. Let an account participate the first campaign first, and then participate in another campaign before the first campaign to end, and then
    a. Set the end time of the second campaign later than the first campaign
    b. Set the end time of the second campaign earlier than the first campaign
    Check their earnings separately to see if they are normal.

Optimize code style

When using cargo +nightly clippy, a lot of errors occurs, some errors are about unnecessary clone, I think if we accept these suggestions, we will get better performance.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.