Skip to content

Commit

Permalink
Add crypto into key pairs and address through CryptoPP 为祖国母亲庆生而提交的代码
Browse files Browse the repository at this point in the history
  • Loading branch information
codrush committed Oct 3, 2018
1 parent 5f7705f commit 5c785c7
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 106 deletions.
23 changes: 17 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
# tinychain
A mini blockchain implementation in C++14

构建迷你区块链——《深入浅出区块链》

## 简要说明 Smmary
tinychain是一个业余的项目,旨在为大家提供微型的简单易懂的供学习的代码。
以下是涉及的一些基础技术:
* 加密库 - RSA
* 本地持久化存储 - sqlite3
* P2P网络 - 暂定gossip
* 网络文本协议 - JSON-RPC
* HTTP Server - mongoose

## toolchain
* gcc/clang support C++14
* boost 1.56+ (datetime)
* cmake
* git
* sqlite3 (apt-get install libsqlite3-dev / brew install sqlite3)
* cryptopp (apt-get install libcryptopp-dev / brew install cryptopp)

## build
On workpath of tinychain:
Expand Down Expand Up @@ -42,12 +53,12 @@ Specifically, run on Windows (example):
```

## 开发路径(TODO-LIST)
1. 基础代码
1. PoW 挖矿代码
1. P2P网络
1. 加密与账户模型
1. 命令行与展示
1. 共识可替换为PoS/DPoS etc
1. 基础代码 - (DONE, to be improved)
1. PoW 挖矿代码 - (DONE, to be improved)
1. 加密与账户模型 (DOING)
1. P2P网络- (TODO)
1. 命令行与Web动态演示 - (DOING)
1. 共识可替换为PoS/DPoS etc - (TODO)

## 仓库介绍
* cli-tinychain文件夹:命令行
Expand Down
7 changes: 1 addition & 6 deletions include/tinychain/blockchain.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,7 @@ class blockchain

Json::Value list_keys(){
Json::Value root;
key_pair_database::key_pair_list_t key_list;
key_pair_database_.list_keys(key_list);

for (const auto& each : key_list) {
root.append(each.to_json());
}
key_pair_database_.list_keys(root);
return root;
}

Expand Down
2 changes: 1 addition & 1 deletion include/tinychain/database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class key_pair_database:public database

key_pair get_new_key_pair();

bool list_keys(key_pair_list_t& key_list);
bool list_keys(Json::Value& root);

private:
sqlite3pp::database db_conn_{db_name_};
Expand Down
83 changes: 61 additions & 22 deletions include/tinychain/tinychain.hpp
Original file line number Diff line number Diff line change
@@ -1,79 +1,118 @@
#pragma once

#include <tinychain/logging.hpp>
#include <jsoncpp/json/json.h>
#include <tinychain/sha256.hpp>

#include <string>
#include <array>
#include <random>
#include <sstream>

// Digital Signatue Algorithm
#include <cryptopp/rsa.h>
#include <cryptopp/base64.h>
#include <cryptopp/osrng.h>
#include <cryptopp/pssr.h>
#include <cryptopp/whrlpool.h>

namespace tinychain
{

namespace tc = tinychain;

// ---------------------------- typedef ----------------------------
typedef std::string sha256_t;
typedef sha256_t public_key_t;
typedef std::string address_t;
typedef CryptoPP::RSA::PublicKey public_key_t;
typedef CryptoPP::RSA::PrivateKey private_key_t;

// ---------------------------- ulitity ----------------------------
sha256_t to_sha256(Json::Value jv);
uint64_t get_now_timestamp();
uint64_t pseudo_random();
sha256_t to_sha256(Json::Value jv);
address_t key_to_address(const public_key_t& public_key);
address_t key_to_address(const private_key_t& private_key);

// ---------------------------- class ----------------------------
class key_pair
{
public:

public:
// new key pair
key_pair() {
private_key_ = pseudo_random();
public_key_ = sha256(std::to_string(private_key_));
private_key_.GenerateRandomWithKeySize(rng, 1024);
}
// Copy
key_pair(const key_pair& rk) {
private_key_ = rk.private_key();
public_key_ = rk.public_key();
}
// =
key_pair& operator=(const key_pair& rk) {
private_key_ = rk.private_key();
public_key_ = rk.public_key();
return *this;
}
key_pair(public_key_t pubk, int prik) {
private_key_ = static_cast<uint64_t>(prik);
public_key_ = pubk;

// 从base64直接构造RSA私钥
key_pair(std::string& encoded_prik) {

log::debug("key_pair-in")<<encoded_prik;
// decode base64 into private key
CryptoPP::StringSource prik_ss(encoded_prik, true, new CryptoPP::Base64Decoder());
private_key_.BERDecode(prik_ss);
log::debug("key_pair-out")<<to_json();
}

key_pair(key_pair&&) = default;
// TODO
key_pair(key_pair&&) = default;
key_pair& operator=(key_pair&&) = default;

void print(){log::info("key_pair")<<"pub:["<<public_key_<<"] pri:["<<private_key_<<"]";}
void print(){log::info("key_pair")<<to_json();}
void test();

// address 1 开头,截取0~31位公钥
address_t address() const { return ("1" + public_key_.substr(0, 30)); }
sha256_t public_key() const { return public_key_; }
uint64_t private_key() const { return private_key_; }
address_t address() const {
return key_to_address(private_key_);
}

private_key_t private_key() const { return private_key_; }

auto encode_pair() const {
// get public key
public_key_t public_key(private_key_);

// encode with base64
std::string encoded_prik, encoded_pubk;
CryptoPP::Base64Encoder prik_slink(new CryptoPP::StringSink(encoded_prik), false);//false for no '\n'
CryptoPP::Base64Encoder pubk_slink(new CryptoPP::StringSink(encoded_pubk), false);
private_key_.DEREncode(prik_slink);
public_key.DEREncode(pubk_slink);
prik_slink.MessageEnd();//base64 编码补足=
pubk_slink.MessageEnd();
//log::debug("key_pair-0")<<encoded_prik;

return std::make_pair(encoded_prik, encoded_pubk);
}

Json::Value to_json() const {
Json::Value root;
auto&& keypair = encode_pair();
root["address"] = address();
root["public_key"] = public_key_;
root["private_key"] = private_key_;
root["public_key"] = keypair.second;
root["private_key"] = keypair.first;
return root;
}

public:
CryptoPP::AutoSeededRandomPool rng;

private:
uint64_t private_key_;
sha256_t public_key_;
private_key_t private_key_;
};

class tx
{
public:
typedef std::pair<sha256_t, uint8_t> input_item_t;
typedef std::pair<public_key_t, uint64_t> output_item_t;
typedef std::pair<address_t, uint64_t> output_item_t;

typedef std::vector<input_item_t> input_t;
typedef std::vector<output_item_t> output_t;
Expand Down
4 changes: 2 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ ADD_EXECUTABLE(tinychain ${tinychain_SOURCES})
IF(WIN32)
TARGET_LINK_LIBRARIES(tinychain ${Boost_LIBRARIES} ${jsoncpp_LIBRARY} ${mongoose_LIBRARY} ${sqlite_LIBRARY})
ELSEIF(ENABLE_SHARED_LIBS)
TARGET_LINK_LIBRARIES(tinychain ${Boost_LIBRARIES} ${jsoncpp_LIBRARY} ${mongoose_LIBRARY} sqlite3)
TARGET_LINK_LIBRARIES(tinychain ${Boost_LIBRARIES} ${jsoncpp_LIBRARY} ${mongoose_LIBRARY} sqlite3 cryptopp)
ELSE()
TARGET_LINK_LIBRARIES(tinychain ${Boost_LIBRARIES} ${jsoncpp_LIBRARY} ${mongoose_LIBRARY} sqlite3 dl)
TARGET_LINK_LIBRARIES(tinychain ${Boost_LIBRARIES} ${jsoncpp_LIBRARY} ${mongoose_LIBRARY} sqlite3 cryptopp dl)
ENDIF()

INSTALL(TARGETS tinychain DESTINATION bin)
Expand Down
20 changes: 12 additions & 8 deletions src/database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ void database::init(){
cmd.execute();

sqlite3pp::command cmd2(db_conn, "create table if not EXISTS key_pairs( \
private_key char(64) primary key, \
public_key char(64) not null, \
address char(64) primary key, \
private_key BLOB NOT NULL, \
account TEXT NOT NULL DEFAULT 'default');");
cmd2.execute();

Expand All @@ -58,23 +58,27 @@ void database::init(){
db_conn.disconnect();
}

//使用CryptoPP的RSA库生成新的密钥对
key_pair key_pair_database::get_new_key_pair() {
key_pair key;
log::info("database")<<"getnewkey address:"<< key.address();
sqlite3pp::transaction xct(db_conn_);
sqlite3pp::command cmd(db_conn_, "INSERT INTO key_pairs (public_key, private_key) VALUES (?, ?)");
//TODO change pub pri key algorithm
cmd.binder() << key.public_key().c_str()<<std::to_string(key.private_key()).c_str();
sqlite3pp::command cmd(db_conn_, "INSERT INTO key_pairs (address, private_key) VALUES (?, ?)");
auto&& keypair = key.encode_pair();
cmd.binder() << key.address() << keypair.first;
cmd.execute();
xct.commit();
return key;
}

bool key_pair_database::list_keys(key_pair_list_t& key_list) {
sqlite3pp::query qry(db_conn_, "SELECT public_key, private_key FROM key_pairs");
// 从数据库中读取数据
bool key_pair_database::list_keys(Json::Value& root) {
sqlite3pp::query qry(db_conn_, "SELECT private_key FROM key_pairs");

for (sqlite3pp::query::iterator i = qry.begin(); i != qry.end(); ++i) {
key_list.push_back(key_pair((*i).get<char const*>(0), (*i).get<int>(1)));
std::string private_key{(*i).get<char const*>(0)};
key_pair each(private_key);
root.append(each.to_json());
}
return true;
}
Expand Down
74 changes: 14 additions & 60 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include <tinychain/tinychain.hpp>
#include <tinychain/node.hpp>
#include <metaverse/mgbubble.hpp>
#include <metaverse/mgbubble.hpp>

using namespace tinychain;
using namespace mgbubble;
Expand All @@ -11,64 +11,28 @@ Logger logger;
int main(int argc, char* argv[])
{

// 初始化本地数据库
database d;
d.init();
d.print();

#if 0
log::info("main")<<"started";
try {
sqlite3pp::database db("test.db");
sqlite3pp::database db2("test.db");
{
sqlite3pp::command cmd(db, "create table if not EXISTS block ( \
number bigint primary KEY , \
hash char(64) not null, \
bits bigint, \
transaction_count INTEGER , \
mixhash VARCHAR (128), \
version char(8) , \
merkle_tree_hash char(64), \
previous_block_hash CHAR (64), \
nonce varchar(128) , \
time_stamp bigint);");
std::cout << cmd.execute() << std::endl;
//sqlite3pp::transaction xct(db);
{
sqlite3pp::command cmd(db, "INSERT INTO block(number, hash, bits) VALUES ('0','AAAA', '1234')");
sqlite3pp::command cmd1(db, "INSERT INTO block(number, hash, bits) VALUES ('1','AAAB', '1235')");
sqlite3pp::command cmd2(db2, "INSERT INTO block(number, hash, bits) VALUES ('2','AAAC', '1236')");
sqlite3pp::command cmd3(db, "INSERT INTO block(number, hash, bits) VALUES ('3','AAAD', '1237')");
sqlite3pp::command cmd4(db2, "INSERT INTO block(number, hash, bits) VALUES ('4','AAAE', '1238')");
std::cout <<"cmd:"<< cmd.execute() << std::endl;
std::cout <<"cmd1:"<< cmd1.execute() << std::endl;
std::cout <<"cmd2:"<< cmd2.execute() << std::endl;
std::cout <<"cmd3:"<< cmd3.execute() << std::endl;
std::cout <<"cmd4:"<< cmd4.execute() << std::endl;
}
}
sqlite3pp::query qry(db2, "SELECT number, hash, bits FROM block");
std::cout << "column:"<< qry.column_count()<<std::endl;
for (sqlite3pp::query::iterator i = qry.begin(); i != qry.end(); ++i) {
int id;
char const* name, *phone;
std::tie(id, name, phone) = (*i).get_columns<int, char const*, char const*>(0, 1, 2);
std::cout << id << "\t" << name << "\t" << phone << std::endl;
}
std::cout << "disconnect db:"<<db.disconnect() << std::endl;
// 初始化本地JSON-RPC服务
node my_node;
mgbubble::RestServ Server{"webroot", my_node};
auto& conn = Server.bind("0.0.0.0:8000");
mg_set_protocol_http_websocket(&conn);
mg_set_timer(&conn, mg_time() + mgbubble::RestServ::session_check_interval);

} catch (std::exception& ex) {
std::cout << ex.what() << std::endl;
}
return 0;
#endif
// 启动本地JSON-RPC服务
log::info("main")<<"httpserver started";
Server.run();


#if 0 //测试用代码 后续会移除
//std::string input = "grape";
//auto&& output1 = sha256(input);
//log::info("main") << "sha256('"<< input << "'):" << output1;
//

#if 0

tx tx1("tx1_address", 100);
tx tx2("tx2_address", 200);

Expand All @@ -94,16 +58,6 @@ int main(int argc, char* argv[])
blockchain1.print();
#endif

// server setup
node my_node;
mgbubble::RestServ Server{"webroot", my_node};
auto& conn = Server.bind("0.0.0.0:8000");
mg_set_protocol_http_websocket(&conn);
mg_set_timer(&conn, mg_time() + mgbubble::RestServ::session_check_interval);

log::info("main")<<"httpserver started";
Server.run();

return 0;
}

Loading

0 comments on commit 5c785c7

Please sign in to comment.