Skip to content

Commit

Permalink
Day 6 通讯协议
Browse files Browse the repository at this point in the history
  • Loading branch information
qikh committed Mar 1, 2017
1 parent 00e44cf commit 38a9a02
Show file tree
Hide file tree
Showing 43 changed files with 2,041 additions and 213 deletions.
6 changes: 3 additions & 3 deletions LICENSE
Expand Up @@ -42,7 +42,7 @@
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
separable from, or merely link (or bind by nodeId) to the interfaces of,
the Work and Derivative Works thereof.

"Contribution" shall mean any work of authorship, including
Expand Down Expand Up @@ -182,11 +182,11 @@
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
file or class nodeId and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright {yyyy} {name of copyright owner}
Copyright {yyyy} {nodeId of copyright owner}

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
5 changes: 5 additions & 0 deletions build.gradle
Expand Up @@ -30,6 +30,11 @@ dependencies {
compile "com.madgag.spongycastle:prov:1.54.0.0"
compile "com.typesafe:config:1.3.1"
compile "org.iq80.leveldb:leveldb:0.9"
compile "org.slf4j:slf4j-api:1.7.23"
compile "org.slf4j:slf4j-log4j12:1.7.23"
compile "log4j:log4j:1.2.17"
compile "io.netty:netty-all:4.1.8.Final"
compile "io.reactivex.rxjava2:rxjava:2.0.6"
testCompile "junit:junit:4.12"
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
Expand Down
38 changes: 38 additions & 0 deletions src/main/kotlin/mbc/MiniBlockChain.kt
@@ -0,0 +1,38 @@
package mbc

import mbc.config.BlockChainConfig
import mbc.network.client.PeerClient
import mbc.network.server.PeerServer

fun main(args: Array<String>) {
val mbc = MiniBlockChain()
mbc.init()
mbc.start()
}

class MiniBlockChain {

var config: BlockChainConfig

constructor() : this(BlockChainConfig.default())

constructor(config: BlockChainConfig) {
this.config = config


}

lateinit var peerClient: PeerClient

lateinit var peerServer: PeerServer

fun init() {

// 检查NodeId,如果不存在就自动生成NodeId。
val nodeId = config.getNodeId()

}

fun start() {
}
}
258 changes: 173 additions & 85 deletions src/main/kotlin/mbc/config/BlockChainConfig.kt
Expand Up @@ -2,126 +2,214 @@ package mbc.config

import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory
import mbc.core.AccountState
import mbc.core.Block
import mbc.core.Transaction
import mbc.serialization.AccountStateSerialize
import mbc.serialization.BlockSerialize
import mbc.serialization.TransactionSerialize
import mbc.storage.DataSource
import mbc.storage.LevelDbDataSource
import mbc.storage.MemoryDataSource
import mbc.storage.ObjectStore
import mbc.util.CryptoUtil
import org.joda.time.DateTime
import org.slf4j.LoggerFactory
import org.spongycastle.util.encoders.Hex
import java.io.File
import java.io.FileReader
import java.io.FileWriter
import java.math.BigInteger
import java.security.PrivateKey
import java.util.*

class BlockChainConfig {

private val DEFAULT_PEER_LISTEN_PORT = 9333

private val DEFAULT_PEER_CONNECTION_TIMEOUT = 10

private val DEFAULT_PEER_VERSION = 0x01

private val MAINNET_NETWORK_ID = 1

enum class DATABASE_TYPE {
MEMORY, LEVELDB
}

companion object {
var minerCoinBase: ByteArray = ByteArray(0)
private var minerCoinBase: ByteArray = ByteArray(0)

var defaultConfig: Config = ConfigFactory.empty()
private var defaultConfig: Config

fun getConfig(): Config {
if (defaultConfig.isEmpty) {
val resourceConfig = ConfigFactory.parseResources("application.conf")
val fileConfig = ConfigFactory.parseFile(File("application.conf"))
private val logger = LoggerFactory.getLogger(this.javaClass)

defaultConfig = defaultConfig.withFallback(resourceConfig).withFallback(fileConfig)
} else {
return defaultConfig
}
constructor() {
this.defaultConfig = ConfigFactory.load()
}

constructor(config: Config) : this() {
this.defaultConfig = config
}

constructor(configFile: File) : this(ConfigFactory.parseFile(configFile))

constructor(resource: String) : this(ConfigFactory.parseResources(resource))

companion object {
fun default(): BlockChainConfig {
return BlockChainConfig()
}
}

fun getConfig(): Config {
if (defaultConfig.isEmpty) {
val fileConfig = ConfigFactory.parseFile(File("conf" + File.separator + "application.conf"))

defaultConfig = defaultConfig.withFallback(fileConfig)
} else {
return defaultConfig
}
return defaultConfig
}

/**
* Account State的存储类组装。
*/
fun getAccountStateStore(): ObjectStore<AccountState> {
val dbName = "accounts"
var ds: DataSource<ByteArray, ByteArray> = MemoryDataSource(dbName)
if (getDatabaseType().equals(DATABASE_TYPE.LEVELDB.name, true)) {
ds = LevelDbDataSource(dbName)
/**
* 得到矿工的Coinbase地址。
*/
fun getMinerCoinbase(): ByteArray {
if (this.minerCoinBase.size > 0) {
return minerCoinBase
} else {
if (getConfig().hasPathOrNull("miner.coinbase")) {
minerCoinBase = Hex.decode(getConfig().getString("miner.coinbase"))
return minerCoinBase;
} else {
throw RuntimeException("Miner Coinbase is empty")
}
ds.init()
return ObjectStore(ds, AccountStateSerialize())
}
}

/**
* Block的存储类组装。
*/
fun getBlockStore(): ObjectStore<Block> {
val dbName = "blocks"
var ds: DataSource<ByteArray, ByteArray> = MemoryDataSource(dbName)
if (getDatabaseType().equals(DATABASE_TYPE.LEVELDB.name, true)) {
ds = LevelDbDataSource(dbName)
}
ds.init()
return ObjectStore(ds, BlockSerialize())
/**
* 设置矿工的Coinbase地址。
*/
fun setMinerCoinbase(newCoinbase: ByteArray) {
this.minerCoinBase = newCoinbase
}

/**
* Key-Value存储的实现。
*/
fun getDatabaseType(): String {
if (getConfig().hasPathOrNull("database.type")) {
return getConfig().getString("database.type")
} else {
return DATABASE_TYPE.MEMORY.name
}
}

/**
* Transaction的存储类组装。
*/
fun getTransactionStore(): ObjectStore<Transaction> {
val dbName = "transactions"
var ds: DataSource<ByteArray, ByteArray> = MemoryDataSource(dbName)
if (getDatabaseType().equals(DATABASE_TYPE.LEVELDB.name, true)) {
ds = LevelDbDataSource(dbName)
}
ds.init()
return ObjectStore(ds, TransactionSerialize())
/**
* 数据库的存储目录。
*/
fun getDatabaseDir(): String {
if (getConfig().hasPathOrNull("database.dir")) {
return getConfig().getString("database.dir")
} else {
return "database"
}
}

/**
* 得到矿工的Coinbase地址。
*/
fun getMinerCoinbase(): ByteArray {
if (this.minerCoinBase.size > 0) {
return minerCoinBase
/**
* 节点的Private Key,如果没有配置私钥则自动生成公私钥对。
*/
fun getNodeKey(): PrivateKey {
val config = getConfig()
if (config.hasPath("peer.privateKey")) {
val key = config.getString("peer.privateKey")
if (key.length != 64) {
throw RuntimeException("The peer.privateKey needs to be Hex encoded and 32 byte length")
}
return CryptoUtil.deserializePrivateKey(Hex.decode(key))
} else {
val file = File(getDatabaseDir(), "nodeId.properties")
val props = Properties()
if (file.canRead()) {
FileReader(file).use({ r -> props.load(r) })
val key = props.getProperty("nodeIdPrivateKey")
return CryptoUtil.deserializePrivateKey(Hex.decode(key))
} else {
if (getConfig().hasPathOrNull("miner.minerCoinBase")) {
minerCoinBase = Hex.decode(getConfig().getString("miner.minerCoinBase"))
return minerCoinBase;
val key = CryptoUtil.generateKeyPair()
if (key != null) {
props.setProperty("nodeIdPrivateKey", Hex.toHexString(key.private.encoded))
props.setProperty("nodeId", Hex.toHexString(key.public.encoded))
file.parentFile.mkdirs()
FileWriter(file).use({ w ->
props.store(w, "自动生成的NodeID,可以设置'peer.privateKey'来替换成自定义的NodeId")
})
logger.info("自动生成NodeID: " + props.getProperty("nodeId"))
logger.info("NodeID与私钥保存在 " + file)

return key.private
} else {
throw RuntimeException("Miner Coinbase is empty")
throw Exception("NodeId or PrivateKey can not be empty.")
}
}
}
}

/**
* 节点的NodeId(PublicKey的序列化)。
*/
fun getNodeId(): String {
val privateKey = getNodeKey()
val publicKey = CryptoUtil.generatePublicKey(privateKey)
return Hex.toHexString(publicKey?.encoded)
}


/**
* 设置矿工的Coinbase地址。
*/
fun setMinerCoinbase(newCoinbase: ByteArray) {
this.minerCoinBase = newCoinbase
/**
* 节点的监听端口。
*/
fun getPeerListenPort(): Int {
val config = getConfig()
if (config.hasPath("peer.listen.port")) {
return config.getInt("peer.listen.port")
}

/**
* Key-Value存储的实现。
*/
fun getDatabaseType(): String {
if (getConfig().hasPathOrNull("database.type")) {
return getConfig().getString("database.type")
} else {
return DATABASE_TYPE.MEMORY.name
}
return DEFAULT_PEER_LISTEN_PORT
}

/**
* 节点的连接超时(秒)。
*/
fun getPeerConnectionTimeout(): Int {
val config = getConfig()
if (config.hasPath("peer.connection.timeout")) {
return config.getInt("peer.connection.timeout")
}

/**
* 数据库的存储目录。
*/
fun getDatabaseDir(): String {
if (getConfig().hasPathOrNull("database.dir")) {
return getConfig().getString("database.dir")
} else {
return "database"
}
return DEFAULT_PEER_CONNECTION_TIMEOUT * 1000
}

/**
* 协议版本。
*/
fun getPeerVersion(): Int {
val config = getConfig()
if (config.hasPath("peer.version")) {
return config.getInt("peer.version")
}

return DEFAULT_PEER_VERSION
}

fun getClientId(): String {
return "MiniBlockChain Kotlin Client"
}

fun getGenesisBlock(): Block {
val genesisBlock = Block(1, 0, ByteArray(0), CryptoUtil.merkleRoot(emptyList()),
Hex.decode("1234567890123456789012345678901234567890"),
DateTime(2017, 2, 1, 0, 0), 0, 0, BigInteger.ZERO, emptyList())
return genesisBlock
}

fun getNetworkId(): Int {
val config = getConfig()
if (config.hasPath("peer.networkId")) {
return config.getInt("peer.networkId")
}

return MAINNET_NETWORK_ID
}

}
5 changes: 0 additions & 5 deletions src/main/kotlin/mbc/core/Account.kt
@@ -1,8 +1,6 @@
package mbc.core

import mbc.storage.Repository
import mbc.util.CryptoUtil
import java.math.BigInteger
import java.security.PublicKey

/**
Expand All @@ -14,7 +12,4 @@ import java.security.PublicKey
class Account(val publicKey: PublicKey) {
val address: ByteArray
get() = CryptoUtil.generateAddress(publicKey)

val balance: BigInteger
get() = Repository.getBalance(address)
}

0 comments on commit 38a9a02

Please sign in to comment.