Ed25519算法
公共钥只有32字节,私钥只有64字节
Curve25519/Ed25519/X25519 是著名密码学家 Daniel J. Bernstein 在 2006 年独立设计的椭圆曲线加密 /签名 /密钥交换算法,和现有的任何椭圆曲线算法都完全独立
Curve25519 是目前最高水平的 Diffie-Hellman函数,适用于广泛的场景,由Daniel J. Bernstein教授设计。由于NIST P-256的设计过程不透明,有来历不明的参数,被广泛怀疑有后门,所以设计了Curve25519,Curve25519的设计过程完全公开,没有任何来历不明的参数。
完全开放设计,算法各个参数直接了当,明确,很大的概率通过缓存、时间、恶意输入摧毁安全性,而 25519 系列椭圆曲线经过特别设计,尽可能的将出错的概率降到了最低,25519 系列曲线是目前最快的椭圆曲线加密算法,NIST 采用的椭圆曲线中有一些诡异的参数,这些参数被广泛地认为是NSA植入的后门。
不足
由于密钥空间是非线性的,无法兼容 BIP 的 Hierarchical Deterministic Key Derivation。
https://cardanolaunch.com/assets/Ed25519_BIP.pdf
mac install tomcat 9.0
check java environment
Tomcat 9.x requires Java 8 or later.
java -version |
Installing Tomcat
- download binary distribution apache-tomcat-9.0.14 from here
- extract to /usr/local/apache-tomcat-9.0.14
- remove old link and create new one
sudo rm -f /Library/Tomcat |
- change ownership and permission
sudo chown -R <your_username> /Library/Tomcat |
- start and stop
/Library/Tomcat/bin/startup.sh |
browse http://localhost:8080
substrate Create a Custom chain
展示如何构建一个 Substrate 区块链的 Runtime Library
先决条件
- make sure node and npm is installed
- Rust and other dependencies for substrate
curl https://getsubstrate.io -sSf | bash |
进入到上面的项目中。
./substrate-node-new substrate-node-template <author-name> |
This will create a folder called substrate-node-template and substrate-ui with the corresponding repositories cloned in them.
Launch a Blockchain
If you have set up everything correctly, you can now start a substrate dev chain! In substrate-node-template run:
./target/release/substrate-node-template --dev |
if you run into any errors starting or running your node, you may need to purge the chain files on your computer. You can do this by running:
// 优先使用这个 |
If everything is working it should start producing blocks!
To interact with the blockchain, you need to start the Substrate UI. Navigate to the substrate-ui folder and run:
npm run dev |
Finally, if open your browser to http://localhost:8000, you should be able to interact with your new chain!
Add Alice to your network
Alice is a hard-coded account in the substrate system, which is pre-funded to make your life easier. Alice may already be added to your network if you used the latest version of the substrate-node-template.
subkey restore Alice |
Then in the Substrate UI, you can go into the Wallet section and add Alice using her seed and name.
If all is working correctly, you can now go into the Send Funds section and send funds from Alice to Default. You will see that Alice has a bunch of units pre-funded in her account, so send some and wait for the green checkmark and an updated balance for Default to show that the transfer has been successfully recorded on the blockchain.
Create a new runtime module
Now it’s time to create our own runtime.
Open up the substrate-node-template folder and create a new file:
./runtime/src/demo.rs |
This is where our new runtime module will live. Inline comments will hopefully give you insight to what the code is doing.
First, we will need to import a few libraries at the top of our file:
// Encoding library |
All modules need to expose a configuration trait. In this case, our trait inherits from the Balances module’s trait since we will be using features and functions made available to us there.
pub trait Trait: balances::Trait {} |
Upgrade our chain
substrate 翻译Substrate in a nutshell
今天我们讨论一下 Substrate,可以帮助你构建定制化区块链的库。 Substrate 是由 Parity Technologies 创建,并且为 Polkadot 提供基础设施。
什么是 Substrate?
从字典定义,或者字面理解 Substrate 可以用来构建,或者发展某些项目。在我们这里,我们可以构建区块链,对于 Polkadot 来说,是构建整个区块链家族。
为什么我们需要 Substrate?
软件充满了抽象。计算机科学的历史展示给我们的就是不断的抽象,从硬件,到开发语言,编程接口。
每个抽象层都想要解决特定的问题。Substrate 想要解决什么问题呢?
在回答这个问题之前,我们先看一下,在你想要实现一个全新的区块链,要考虑哪些方面:
- 为什么需要另一个区块链?!
- 各种各样的原始加密算法,签名等等.
- 共识算法和容错选举.
- POW,POS或者完全不同的概念?
- 区块结构,高效存储,信息序列化.
- P2P 网络, 节点发现, 区块和交易传播.
- 状态机,运行时,智能合约.
- 轻客户端的支持
尽管 Substrate 不能帮你实现第一条,至少可以帮你做余下的事情。开箱即用的实现,是基于多年开发区块链的经验,设计,实现,极度用心的测试。
通过提供典型算法的通用实现,可以使开发者专注于项目的业务逻辑,比如:状态机。
让我们看看区块链最核心的部分,以及 Substrate 可以为我们做什么。
区块链的持久化
区块链唯一的目的就是在非可信环境下,提供一个途径可以在任意时间点验证,达成共识,全局持久化,并且一旦确认真实可靠,就不可更改。
Substrate 提供了一种高效并且非常易用的,和 Wasm 运行时紧密继承的持久化。
区块链作为函数
为了更新区块链状态,根据挂起的操作更改存储,我们需要一个时间点来执行这些操作。
这些时间的可以表示为一个函数,根据当前的状态和挂起的操作,生成另一个状态,可以认为是区块链的真实当前状态。我们把这个函数称作 state transition function 或者简称 STF
Substrate 允许开发者以一种可管理,可移植的方式来定义这个函数。就像 Web 页面执行的 JavaScript 一样,可以提供一组函数作为运行时来提供 STF 服务。此外该实现可以是可移植的,跨平台的,支持浏览器等等方式。
Substrate 使用 WebAssembly 作为通用的运行时。
安全和速度
使用 WebAssembly 实现业务逻辑和智能合约意味着可以借用现有的工具快速可靠的执行。Substrate 提供了另一种可以更快执行代码的途径-没有虚拟机的开销。
Substrate 具有革命性创新之一的就是运行时镜像和 STF 同其他数据一样保存在链上。这意味着,运行时和链的业务逻辑可以通过安全,可校验的方式来更新。并且 Substrate 和 Substrate Runtime Module Library(SRML)是使用 Rust 语言实现的,可以编译为本地代码和 Wasm。
在任意时间点,客户端拥有两份已编译的运行时。一个是本地编译的,一个是 Wasm 镜像可以在 VM 里面执行。当执行运行时函数时,客户端先检查链上的运行时版本和本地的版本是否一致,如果一致,执行本地的版本。
不分叉的升级
当链上的运行时镜像升级,一些客户端软件没有升级时,客户端会使用链上的运行时镜像版本来执行。所以在任何时候,所有节点都能够正确的同步区块,防止分叉。
网络
使用了 libp2p 库来实现去中心化网络环境。
译者注:libp2p 是 IPFS 项目分出来的独立项目。
定制消息
对于简单的场景,你不需要考虑网络,因为 Substrate 做了所有的事情。你只需要提供区块链的 STF 即可。如果你需要发送定制化信息,可以通过提供特殊化的网络协议定义消息和处理逻辑来定制和扩展网络子系统。
共识
有一个 STF 可以从一个状态转换到另一个状态还不够,还需要所有的节点都对转换后的状态达成共识。
Substrate 实现的每个共识引擎会有一个运行时模块,处理不良行为的证明。评估的处理结果由运行时来决定。
Substrate 提供了一个 BFT 的实现可以开箱即用。并且还会不断的完善,增加其他的算法进来。根据应用场景,开发者可能使用现存在产块逻辑,也可能提供自己的。
Substrate 是一个完全可定制化,可扩展的框架,开发者可以定义自己的共识算法。实际上 Substrate 非常的灵活,可以提供非传统区块链结构的解决方案。
轻客户端支持
全节点需要同步所有的数据,并且不是简单的同步数据,出于安全原因考虑,还需要重新执行所有交易,计算量比较繁重。
Substrate 从设计上就考虑了轻客户端的支持,可以开箱即用。
substrate 入门操作
install
To get going as fast as possible, there is a simple script that installs all required dependencies and installs Substrate into your path. Just open a terminal and run:
curl https://getsubstrate.io -sSf | bash |
You can start a local Substrate development chain with running substrate --dev
Specify the chain specification (one of dev, local or staging)
To create your own global network/cryptocurrency, make a chainspec file
First let’s get a template chainspec that you can edit. We’ll use the “staging” chain, a sort of default chain that the node comes pre-configured with:
substrate --chain=dev build-spec > ~/chainspec.json |
Error: Execution: Instantiation: Export ext_storage_changes_root has different signature Signature { params: [I64, I32], return_type: Some(I32) }
rm -rf ~/.local/share/Substrate/ |
Building from source
curl https://sh.rustup.rs -sSf | sh |
brew install cmake pkg-config openssl git llvm |
git clone https://github.com/paritytech/substrate.git |
You can run the tests if you like:
cargo test --all |
You can start a development chain with:
cargo run -- --dev |
rust functional
- Closures, a function-like construct you can store in a variable
- Iterators, a way of processing a series of elements
- How to use these two features to improve the I/O project in Chapter 12
- The performance of these two features (Spoiler alert: they’re faster than you might think!)
Closure
Closures: Anonymous Functions that Can Capture Their Environment
Rust’s closures are anonymous functions you can save in a variable or pass as arguments to other functions. You can create the closure in one place and then call the closure to evaluate it in a different context. Unlike functions, closures can capture values from the scope in which they’re defined.
#![allow(unused_variables)] |
if has multiple parameter
|param1, param2| |
can add annotation for clarity
#![allow(unused_variables)] |
generic parameter
#![allow(unused_variables)] |
The Cacher struct has a calculation field of the generic type T. The trait bounds on T specify that it’s a closure by using the Fn trait. Any closure we want to store in the calculation field must have one u32 parameter (specified within the parentheses after Fn) and must return a u32 (specified after the ->).
rust error
Rust groups errors into two major categories: recoverable and unrecoverable errors.
Rust doesn’t have exceptions. Instead, it has the type Result<T, E> for recoverable errors and the panic! macro that stops execution when the program encounters an unrecoverable error.
By default, when a panic occurs, the program starts unwinding, which means Rust walks back up the stack and cleans up the data from each function it encounters. But this walking back and cleanup is a lot of work.
If in your project you need to make the resulting binary as small as possible, you can switch from unwinding to aborting
[profile.release] |
rust struct
#![allow(unused_variables)] |
|
|
|
|
method
#[derive(Debug)] |