修改抽签算法,通过伪随机数生成出块人随机序列。

This commit is contained in:
wuwei1972 2018-07-14 20:53:08 +08:00
parent 76c4199fc4
commit 356a6713c2
7 changed files with 295 additions and 34 deletions

View File

@ -19,6 +19,7 @@ import com.google.protobuf.ByteString
/**
* @author c4w
* modify by jiangbuyun
*/
object Sha256 extends CryptographicHash{
override val DigestSize: Int = 32
@ -26,9 +27,15 @@ object Sha256 extends CryptographicHash{
def hashstr(input: Array[Byte]):String ={
BytesHex.bytes2hex(hash(input))
}
def hashstr(input: String):String ={
val iptb = ByteString.copyFromUtf8(input)
BytesHex.bytes2hex(hash(iptb.toByteArray()))
}
def hashToBytes(input: String):Array[Byte] ={
val iptb = ByteString.copyFromUtf8(input)
hash(iptb.toByteArray())
}
}

View File

@ -17,6 +17,7 @@ package rep.network.consensus.vote
import rep.crypto.Sha256
import scala.collection.mutable
import rep.storage.util.pathUtil
/**
* 系统默认
@ -28,23 +29,50 @@ import scala.collection.mutable
*/
//TODO kami 应该在init的时候载入一个实现函数或者类然后调用方法写的更通用一些
trait CRFDVoter extends VoterBase {
case class randomNumber(var number:Long,var generateSerial:Int,var sortPos:Int)
override def blocker(nodes: Set[String], position:Int): Option[String] = {
//if (nodes.nonEmpty&&position<nodes.size) Option(nodes.head) else None
override def blocker(nodes: Array[String], position:Int): String = {
if(nodes.nonEmpty){
var pos = position
if(position >= nodes.size){
pos = position % nodes.size
}
val a = nodes.toList
Option(a(pos))
nodes(pos)
}else{
None
null
}
}
override def candidators(nodes: Set[String], seed: Array[Byte]): Set[String] = {
var nodesSeq = nodes.toSeq.sortBy(f=>(f.toString()))//nodes.toSeq
private def getRandomList(seed:Long,candidatorLen:Int,candidatorTotal:Int):Array[randomNumber]={
val m = 2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2
val a = 2045
val b = 1
var randomArray = new Array[randomNumber](candidatorTotal)
var hashSeed = seed.abs
for(i<-0 to candidatorTotal-1){
var tmpSeed = (a * hashSeed + b) % m
tmpSeed = tmpSeed.abs
if(tmpSeed == hashSeed) tmpSeed = tmpSeed + 1
hashSeed = tmpSeed
var randomobj = new randomNumber(hashSeed,i,-1)
randomArray(i) = randomobj
}
randomArray = randomArray.sortWith(
(randomNumber_left,randomNumber_right)=> randomNumber_left.number < randomNumber_right.number)
for(i<-0 to randomArray.size-1){
randomArray(i).sortPos = i
}
randomArray = randomArray.sortWith(
(randomNumber_left,randomNumber_right)=> randomNumber_left.generateSerial < randomNumber_right.generateSerial)
randomArray
}
override def candidators(nodes: Set[String], seed: Array[Byte]): Array[String] = {
var nodesSeq = nodes.toSeq.sortBy(f=>(f.toString()))
var len = nodes.size / 2 + 1
val min_len = 4
len = if(len<min_len){
@ -53,27 +81,25 @@ trait CRFDVoter extends VoterBase {
}
else len
if(len<4){
Set.empty
null
}
else{
var candidate = mutable.Seq.empty[String]
var index = 0
var hashSeed = seed
//var candidate = mutable.Seq.empty[String]
var candidate = new Array[String](len)
var hashSeed:Long = pathUtil.bytesToInt(seed)
var randomList = getRandomList(hashSeed,len,nodes.size)
//PrintRandomArray(randomList)
println(randomList(0).sortPos)
for(j<-0 to len-1){
var e = randomList(j)
//candidate = (candidate :+ nodesSeq(e.sortPos))
candidate(j) = nodesSeq(e.sortPos)
while (candidate.size < len) {
if (index >= hashSeed.size) {
hashSeed = Sha256.hash(hashSeed)
index = 0
}
//应该按位来计算
if ((hashSeed(index) & 1) == 1) {
candidate = (candidate :+ nodesSeq(index % (nodesSeq.size)))
nodesSeq = (nodesSeq.toSet - nodesSeq(index % (nodesSeq.size))).toSeq
}
index += 1
}
candidate.toSet
//candidate.toSet
candidate
}
}
}

View File

@ -78,7 +78,7 @@ class CRFDVoterModule(moduleName: String) extends ModuleBase(moduleName) with CR
def rnd = ThreadLocalRandom.current
var candidatorCur = Set.empty[ String ]
var candidatorCur : Array[ String ] = null
var isWaiting = false
@ -167,15 +167,15 @@ class CRFDVoterModule(moduleName: String) extends ModuleBase(moduleName) with CR
val seed = pe.getVoteBlockHash//pe.getCurrentBlockHash
candidatorCur = candidators(SystemCertList.getSystemCertList, Sha256.hash(seed))
if (!candidatorCur.isEmpty) {
if (candidatorCur != null) {
pe.resetCandidator(candidatorCur)
if(pe.getCacheHeight() >= 1){
val blo = blocker(candidatorCur, pe.getBlker_index)
if (blo != None) {
pe.resetBlocker(blo.get)
if (blo != null) {
pe.resetBlocker(blo)
//暂时只找到该方法能够明确标识一个在网络中有网络地址的节点后续发现好方法可以完善
logMsg(LOG_TYPE.INFO, s"Select in getCacheHeight=${pe.getCacheHeight()} Candidates : ${candidatorCur} ~ Blocker : ${blo},currenthash=${pe.getCurrentBlockHash},index=${pe.getBlker_index}")
if (pe.getSysTag == blo.get.toString()) {
if (pe.getSysTag == blo) {
getActorRef(ActorType.BLOCK_MODULE) ! (BlockEvent.CREATE_BLOCK, "")
logMsg(LOG_TYPE.INFO, s"Select in getCacheHeight=${pe.getCacheHeight()} Candidates : ${candidatorCur} ,send Create cmd~ Blocker : ${blo},currenthash=${pe.getCurrentBlockHash},index=${pe.getBlker_index}")
}

View File

@ -35,7 +35,7 @@ trait VoterBase {
* @return
*/
//def blocker[T](nodes:Set[T], position:Int):Option[T]
def blocker(nodes:Set[String], position:Int):Option[String]
def blocker(nodes:Array[String], position:Int):String
/**
* 获取候选人节点
@ -45,5 +45,5 @@ trait VoterBase {
* @return
*/
//def candidators[T](nodes:Set[T], seed:Array[Byte]):Set[T]
def candidators(nodes:Set[String], seed:Array[Byte]):Set[String]
def candidators(nodes:Set[String], seed:Array[Byte]):Array[String]
}

View File

@ -260,7 +260,7 @@ class PeerExtensionImpl extends Extension {
}
}
def resetCandidator(nds: Set[ String ]): Unit = {
def resetCandidator(nds: Array[ String ]): Unit = {
candidatorLock.lock()
try{
candidator = immutable.TreeMap.empty[String,String]

View File

@ -0,0 +1,207 @@
package rep.storage.test
import scala.collection.mutable
import rep.crypto.Sha256
import rep.storage.util.pathUtil
object testRandomVote {
case class randomstatis(listsize:Int,clist:scala.collection.mutable.ArrayBuffer[String])
case class randomNumber(var number:Long,var generateSerial:Int,var sortPos:Int)
var statisvar:randomstatis = null
var statis:Array[Int] = null
def getRandomList(seed:Long,candidatorLen:Int,candidatorTotal:Int):Array[randomNumber]={
val m = 2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2
val a = 2045
val b = 1
var randomArray = new Array[randomNumber](candidatorTotal)
var hashSeed = seed.abs
for(i<-0 to candidatorTotal-1){
var tmpSeed = (a * hashSeed + b) % m
tmpSeed = tmpSeed.abs
if(tmpSeed == hashSeed) tmpSeed = tmpSeed + 1
hashSeed = tmpSeed
var randomobj = new randomNumber(hashSeed,i,-1)
randomArray(i) = randomobj
}
randomArray = randomArray.sortWith(
(randomNumber_left,randomNumber_right)=> randomNumber_left.number < randomNumber_right.number)
for(i<-0 to randomArray.size-1){
randomArray(i).sortPos = i
}
randomArray = randomArray.sortWith(
(randomNumber_left,randomNumber_right)=> randomNumber_left.generateSerial < randomNumber_right.generateSerial)
randomArray
}
def PrintRandomArray(ra : Array[randomNumber])={
if(ra == null) println("no data,input is null")
if(ra.size == 0) println("no data, input length is zero")
for(i<-0 to (ra.length-1)){
println("randomnumber="+ra(i).number+",generateSerial="+ra(i).generateSerial+",sortpos="+ra(i).sortPos+"|||")
}
}
def getRandomString(length:Int):String={
val str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
var random=new util.Random()
var sb=new StringBuffer()
for( i<-0 to length-1){
val number= random.nextInt(62)
sb.append(str.charAt(number))
}
sb.toString()
}
def getRandomSha256String(length:Int): Array[Byte]={
val s = getRandomString(length)
//println(Sha256.hashstr(s))
Sha256.hashToBytes(s)
}
def findIndex(indexs:Array[Int],idx:Int):Boolean={
var b = false
for( i<-0 to indexs.length-1){
if(indexs(i) == idx){
b = true
}
}
b
}
def candidators(nodes: Set[String], seed: Array[Byte]): Array[String] = {
var nodesSeq = nodes.toSeq.sortBy(f=>(Integer.parseInt(f.toString())))
var len = nodes.size / 2 + 1
val min_len = 4
len = if(len<min_len){
if(nodes.size < min_len) nodes.size
else min_len
}
else len
if(len<4){
null
}
else{
//var candidate = mutable.Seq.empty[String]
var candidate = new Array[String](len)
var hashSeed:Long = pathUtil.bytesToInt(seed)
var randomList = getRandomList(hashSeed,len,nodes.size)
//PrintRandomArray(randomList)
println(randomList(0).sortPos)
for(j<-0 to len-1){
var e = randomList(j)
//candidate = (candidate :+ nodesSeq(e.sortPos))
candidate(j) = nodesSeq(e.sortPos)
}
//candidate.toSet
candidate
}
}
def blocker(nodes: Array[String], position:Int): String = {
if(nodes.nonEmpty){
var pos = position
if(position >= nodes.size){
pos = position % nodes.size
}
val a = nodes.toList
nodes(pos)
}else{
null
}
}
def getStableNodes(length:Int) :Set[String] = {
var source = Set.empty[String]
for(i <- 0 to length-1){
source += i.toString()
}
source
}
def checkblker(nodecount:Int,pos:Int)={
val c = getStableNodes(nodecount)
val hashbytes = getRandomSha256String(500)
val cs = candidators(c, hashbytes)
val blo = blocker(cs, pos)
//statisvar.clist += blo.toString()
//println(cs.toString()+"\t"+blo.toString())
val idx = Integer.parseInt(blo)
statis(idx) = statis(idx) + 1
//println(blo.toString())
}
def testRandomBlocker(count:Int,nodes:Int,pos:Int){
//statisvar = new randomstatis(count,new scala.collection.mutable.ArrayBuffer[String](count))
statis = new Array[Int](nodes)
for(i<-0 to count-1){
checkblker(nodes,pos)
}
//println(statisvar.clist.toString())
for(j<-0 to statis.length-1) print(","+"blocker="+j+"("+statis(j).toString()+")")
}
def printRandom(size:Int){
for(j<-0 to 1000){
val istr = getRandomSha256String(500)
var i = pathUtil.bytesToInt(istr)
if(i < 0){
i = i.abs
}
println("\t"+i % size)
}
}
def testPrintRandomArray(len:Int,size:Int){
for(j<-0 to 1000){
val istr = getRandomSha256String(500)
var seed = pathUtil.bytesToInt(istr)
var ra = getRandomList(seed,len,size)
PrintRandomArray(ra)
println("-------------------")
}
}
def printRandomlist(size:Int){
val m = 2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2//43112609
val a = 2045//12477 // a = 4p + 1 3119
val b = 1//4667 // b = 2q + 1 2333
var tmpstatis = new Array[Int](size)
val istr = getRandomSha256String(500)
var l = pathUtil.bytesToInt(istr)
if(l < 0){
l = l.abs
}
for(i<-0 to 1000){
l = a*l+b
if(l < 0) l = l.abs
tmpstatis(l % size) = tmpstatis(l % size) +1
println("\t"+l % size)
}
for(j<-0 to tmpstatis.length-1)
print(","+tmpstatis(j))
}
def main(args: Array[String]): Unit = {
//println(pathUtil.IsPrime(2333))
testRandomBlocker(100000,5,0)
//printRandom(4)
//printRandomlist(30)
//testPrintRandomArray(16,30)
}
}

View File

@ -119,4 +119,25 @@ public class pathUtil {
}
return l;
}
public static int bytesToInt(byte[] inputs){
if(inputs == null) return 0;
if(inputs.length < 4) return 0;
return (inputs[0] & 0xff) << 24
| (inputs[1] & 0xff) << 16
| (inputs[2] & 0xff) << 8
| (inputs[3] & 0xff) << 0 ;
}
public static boolean IsPrime(int n){
if (n <= 3) {
return n > 1;
}
for(int i=2;i<=Math.sqrt(n);i++){
if(n%i == 0)
return false;
}
return true;
}
}