github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/mining/tensority/go_algorithm/matrix.go (about) 1 package go_algorithm 2 3 import ( 4 "reflect" 5 "runtime" 6 "sync" 7 "unsafe" 8 9 "gonum.org/v1/gonum/mat" 10 11 "github.com/bytom/bytom/crypto/sha3pool" 12 "github.com/bytom/bytom/protocol/bc" 13 ) 14 15 const ( 16 matSize = 1 << 8 // Size of matrix 17 matNum = 1 << 8 // Number of matrix 18 ) 19 20 func mulMatrix(headerhash []byte, cache []uint32) []uint8 { 21 ui32data := make([]uint32, matNum*matSize*matSize/4) 22 for i := 0; i < 128; i++ { 23 start := i * 1024 * 32 24 for j := 0; j < 512; j++ { 25 copy(ui32data[start+j*32:start+j*32+32], cache[start+j*64:start+j*64+32]) 26 copy(ui32data[start+512*32+j*32:start+512*32+j*32+32], cache[start+j*64+32:start+j*64+64]) 27 } 28 } 29 30 // Convert our destination slice to a int8 buffer 31 header := *(*reflect.SliceHeader)(unsafe.Pointer(&ui32data)) 32 header.Len *= 4 33 header.Cap *= 4 34 i8data := *(*[]int8)(unsafe.Pointer(&header)) 35 36 f64data := make([]float64, matNum*matSize*matSize) 37 for i := 0; i < matNum*matSize*matSize; i++ { 38 f64data[i] = float64(i8data[i]) 39 } 40 41 dataIdentity := make([]float64, matSize*matSize) 42 for i := 0; i < 256; i++ { 43 dataIdentity[i*257] = float64(1) 44 } 45 46 var tmp [matSize][matSize]float64 47 var maArr [4][matSize][matSize]float64 48 49 runtime.GOMAXPROCS(4) 50 var wg sync.WaitGroup 51 wg.Add(4) 52 53 for k := 0; k < 4; k++ { 54 go func(i int) { 55 defer wg.Done() 56 57 ma := mat.NewDense(matSize, matSize, dataIdentity) 58 mc := mat.NewDense(matSize, matSize, make([]float64, matSize*matSize)) 59 60 var sequence [32]byte 61 sha3pool.Sum256(sequence[:], headerhash[i*8:(i+1)*8]) 62 63 for j := 0; j < 2; j++ { 64 for k := 0; k < 32; k++ { 65 index := int(sequence[k]) 66 mb := mat.NewDense(matSize, matSize, f64data[index*matSize*matSize:(index+1)*matSize*matSize]) 67 mc.Mul(ma, mb.T()) 68 69 for row := 0; row < matSize; row++ { 70 for col := 0; col < matSize; col++ { 71 i32v := int32(mc.At(row, col)) 72 i8v := int8((i32v & 0xff) + 73 ((i32v >> 8) & 0xff)) 74 mc.Set(row, col, float64(i8v)) 75 } 76 } 77 ma = mc 78 } 79 } 80 81 for row := 0; row < matSize; row++ { 82 for col := 0; col < matSize; col++ { 83 maArr[i][row][col] = ma.At(row, col) 84 } 85 } 86 }(k) 87 } 88 wg.Wait() 89 90 for i := 0; i < 4; i++ { 91 for row := 0; row < matSize; row++ { 92 for col := 0; col < matSize; col++ { 93 i32vtmp := int32(tmp[row][col]) 94 i32vma := int32(maArr[i][row][col]) 95 i8v := int8(int32(i32vtmp+i32vma) & 0xff) 96 tmp[row][col] = float64(i8v) 97 } 98 } 99 } 100 101 result := make([]uint8, 0) 102 for i := 0; i < matSize; i++ { 103 for j := 0; j < matSize; j++ { 104 result = append(result, uint8(tmp[i][j])) 105 } 106 } 107 return result 108 } 109 110 // hashMatrix hash result of mulMatrix 111 func hashMatrix(result []uint8) *bc.Hash { 112 var mat8 [matSize][matSize]uint8 113 for i := 0; i < matSize; i++ { 114 for j := 0; j < matSize; j++ { 115 mat8[i][j] = result[i*matSize+j] 116 } 117 } 118 119 var mat32 [matSize][matSize / 4]uint32 120 121 for i := 0; i < matSize; i++ { 122 for j := 0; j < matSize/4; j++ { 123 mat32[i][j] = ((uint32(mat8[i][j+192])) << 24) | 124 ((uint32(mat8[i][j+128])) << 16) | 125 ((uint32(mat8[i][j+64])) << 8) | 126 ((uint32(mat8[i][j])) << 0) 127 } 128 } 129 130 for k := matSize; k > 1; k = k / 2 { 131 for j := 0; j < k/2; j++ { 132 for i := 0; i < matSize/4; i++ { 133 mat32[j][i] = fnv(mat32[j][i], mat32[j+k/2][i]) 134 } 135 } 136 } 137 138 ui32data := make([]uint32, 0) 139 for i := 0; i < matSize/4; i++ { 140 ui32data = append(ui32data, mat32[0][i]) 141 } 142 143 // Convert our destination slice to a byte buffer 144 header := *(*reflect.SliceHeader)(unsafe.Pointer(&ui32data)) 145 header.Len *= 4 146 header.Cap *= 4 147 dataBytes := *(*[]byte)(unsafe.Pointer(&header)) 148 149 var h [32]byte 150 sha3pool.Sum256(h[:], dataBytes) 151 bcHash := bc.NewHash(h) 152 return &bcHash 153 } 154 155 func fnv(a, b uint32) uint32 { 156 return a*0x01000193 ^ b 157 }