github.com/cryptoecc/eth-ecc@v0.0.3/consensus/ethash/LDPC_utils.go (about)

     1  package ethash
     2  
     3  import (
     4  	crand "crypto/rand"
     5  	"math"
     6  	"math/big"
     7  	"math/rand"
     8  )
     9  
    10  //Parameters for matrix and seed
    11  const (
    12  	BigInfinity = 1000000.0
    13  	Inf         = 64.0
    14  	MaxNonce    = 1<<32 - 1
    15  
    16  	// These parameters are only used for the decoding function.
    17  	maxIter  = 20   // The maximum number of iteration in the decoder
    18  	crossErr = 0.01 // A transisient error probability. This is also fixed as a small value
    19  )
    20  
    21  type Parameters struct {
    22  	n    int //256
    23  	m    int //34
    24  	wc   int
    25  	wr   int
    26  	seed int
    27  }
    28  
    29  // setParameters sets n, wc, wr, m, seed return parameters and difficulty level
    30  func setParameters(hash []byte) Parameters {
    31  	parameters := Parameters{
    32  		n:  256,
    33  		wc: 3,
    34  		wr: 4,
    35  	}
    36  	parameters.m = int(parameters.n * parameters.wc / parameters.wr)
    37  
    38  	var arrayHash [32]byte
    39  	copy(arrayHash[:], hash[:32])
    40  	parameters.seed = generateSeed(arrayHash)
    41  
    42  	return parameters
    43  }
    44  
    45  //generateRandomNonce generate 64bit random nonce with similar way of ethereum block nonce
    46  func generateRandomNonce() uint64 {
    47  	seed, _ := crand.Int(crand.Reader, big.NewInt(math.MaxInt64))
    48  	source := rand.New(rand.NewSource(seed.Int64()))
    49  
    50  	return uint64(source.Int63())
    51  }
    52  
    53  func funcF(x float64) float64 {
    54  	if x >= BigInfinity {
    55  		return 1.0 / BigInfinity
    56  	} else if x <= (1.0 / BigInfinity) {
    57  		return BigInfinity
    58  	} else {
    59  		return math.Log((math.Exp(x) + 1) / (math.Exp(x) - 1))
    60  	}
    61  }
    62  
    63  func infinityTest(x float64) float64 {
    64  	if x >= Inf {
    65  		return Inf
    66  	} else if x <= -Inf {
    67  		return -Inf
    68  	} else {
    69  		return x
    70  	}
    71  }
    72  
    73  //generateSeed generate seed using previous hash vector
    74  func generateSeed(phv [32]byte) int {
    75  	sum := 0
    76  	for i := 0; i < len(phv); i++ {
    77  		sum += int(phv[i])
    78  	}
    79  	return sum
    80  }
    81  
    82  //generateH generate H matrix using parameters
    83  //generateH Cannot be sure rand is same with original implementation of C++
    84  func generateH(parameters Parameters) [][]int {
    85  	var H [][]int
    86  	var hSeed int64
    87  	var colOrder []int
    88  
    89  	hSeed = int64(parameters.seed)
    90  	k := parameters.m / parameters.wc
    91  
    92  	H = make([][]int, parameters.m)
    93  	for i := range H {
    94  		H[i] = make([]int, parameters.n)
    95  	}
    96  
    97  	for i := 0; i < k; i++ {
    98  		for j := i * parameters.wr; j < (i+1)*parameters.wr; j++ {
    99  			H[i][j] = 1
   100  		}
   101  	}
   102  
   103  	for i := 1; i < parameters.wc; i++ {
   104  		colOrder = nil
   105  		for j := 0; j < parameters.n; j++ {
   106  			colOrder = append(colOrder, j)
   107  		}
   108  
   109  		rand.Seed(hSeed)
   110  		rand.Shuffle(len(colOrder), func(i, j int) {
   111  			colOrder[i], colOrder[j] = colOrder[j], colOrder[i]
   112  		})
   113  		hSeed--
   114  
   115  		for j := 0; j < parameters.n; j++ {
   116  			index := (colOrder[j]/parameters.wr + k*i)
   117  			H[index][j] = 1
   118  		}
   119  	}
   120  
   121  	return H
   122  }
   123  
   124  //generateQ generate colInRow and rowInCol matrix using H matrix
   125  func generateQ(parameters Parameters, H [][]int) ([][]int, [][]int) {
   126  	colInRow := make([][]int, parameters.wr)
   127  	for i := 0; i < parameters.wr; i++ {
   128  		colInRow[i] = make([]int, parameters.m)
   129  	}
   130  
   131  	rowInCol := make([][]int, parameters.wc)
   132  	for i := 0; i < parameters.wc; i++ {
   133  		rowInCol[i] = make([]int, parameters.n)
   134  	}
   135  
   136  	rowIndex := 0
   137  	colIndex := 0
   138  
   139  	for i := 0; i < parameters.m; i++ {
   140  		for j := 0; j < parameters.n; j++ {
   141  			if H[i][j] == 1 {
   142  				colInRow[colIndex%parameters.wr][i] = j
   143  				colIndex++
   144  
   145  				rowInCol[rowIndex/parameters.n][j] = i
   146  				rowIndex++
   147  			}
   148  		}
   149  	}
   150  
   151  	return colInRow, rowInCol
   152  }
   153  
   154  //generateHv generate hashvector
   155  //It needs to compare with origin C++ implementation Especially when sha256 function is used
   156  func generateHv(parameters Parameters, encryptedHeaderWithNonce []byte) []int {
   157  	hashVector := make([]int, parameters.n)
   158  
   159  	/*
   160  		if parameters.n <= 256 {
   161  			tmpHashVector = sha256.Sum256(headerWithNonce)
   162  		} else {
   163  			/*
   164  				This section is for a case in which the size of a hash vector is larger than 256.
   165  				This section will be implemented soon.
   166  		}
   167  			transform the constructed hexadecimal array into an binary array
   168  			ex) FE01 => 11111110000 0001
   169  	*/
   170  
   171  	for i := 0; i < parameters.n/8; i++ {
   172  		decimal := int(encryptedHeaderWithNonce[i])
   173  		for j := 7; j >= 0; j-- {
   174  			hashVector[j+8*(i)] = decimal % 2
   175  			decimal /= 2
   176  		}
   177  	}
   178  
   179  	//outputWord := hashVector[:parameters.n]
   180  	return hashVector
   181  }