You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

233 lines
7.5 KiB

  1. package ringct
  2. import "fmt"
  3. import "github.com/arnaucode/derosuite/crypto"
  4. // this file has license pending since it triggers a hard to find golang bug TODO add license after the golang bug is fixed
  5. /* This file implements MLSAG signatures for the transactions */
  6. // get the hash of the transaction which is used to create the mlsag later on, this hash is input to MLSAG
  7. // the hash is = hash( message + hash(basehash) + hash(pederson and borromean data))
  8. func Get_pre_mlsag_hash(sig *RctSig) crypto.Hash {
  9. message_hash := sig.Message
  10. base_hash := crypto.Keccak256(sig.SerializeBase())
  11. //fmt.Printf("Message hash %s\n", message_hash)
  12. //fmt.Printf("Base hash %s\n", base_hash)
  13. // now join the borromean signature and extract a sig
  14. var other_data []byte
  15. for i := range sig.rangeSigs {
  16. //other_data = append(other_data,sig.rangeSigs[i].asig.s0.Serialize()...)
  17. //other_data = append(other_data,sig.rangeSigs[i].asig.s1.Serialize()...)
  18. //other_data = append(other_data,sig.rangeSigs[i].asig.ee[:]...)
  19. //OR
  20. // other_data = append(other_data, sig.rangeSigs[i].asig.Serialize()...) // serialise borrosig
  21. // other_data = append(other_data, sig.rangeSigs[i].ci.Serialize()...)
  22. // OR
  23. other_data = append(other_data, sig.rangeSigs[i].Serialize()...) // range sig serialise
  24. }
  25. other_data_hash := crypto.Keccak256(other_data)
  26. //fmt.Printf("other hash %s\n", other_data_hash)
  27. // join all 3 hashes and hash them again to get the data
  28. final_data := append(message_hash[:], base_hash[:]...)
  29. final_data = append(final_data, other_data_hash[:]...)
  30. final_data_hash := crypto.Keccak256(final_data)
  31. if DEBUGGING_MODE {
  32. fmt.Printf("final_data_hash hash %s\n", final_data_hash)
  33. }
  34. return final_data_hash
  35. }
  36. //Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures)
  37. //This is a just slghtly more efficient version than the ones described below
  38. //(will be explained in more detail in Ring Multisig paper
  39. //These are aka MG signatutes in earlier drafts of the ring ct paper
  40. // c.f. http://eprint.iacr.org/2015/1098 section 2.
  41. // keyImageV just does I[i] = xx[i] * Hash(xx[i] * G) for each i
  42. // Gen creates a signature which proves that for some column in the keymatrix "pk"
  43. // the signer knows a secret key for each row in that column
  44. // Ver verifies that the MG sig was created correctly
  45. func MLSAG_Ver(message Key, pk [][]Key, rv *MlsagSig, dsRows int, r *RctSig) (result bool) {
  46. result = false
  47. cols := len(pk)
  48. if cols < 2 {
  49. if DEBUGGING_MODE {
  50. fmt.Printf("RingCT MLSAG_Ver must have cols > 1\n")
  51. }
  52. result = false
  53. return
  54. }
  55. rows := len(pk[0])
  56. if rows < 1 {
  57. if DEBUGGING_MODE {
  58. fmt.Printf("RingCT MLSAG_Ver must have rows > 0\n")
  59. }
  60. result = false
  61. return
  62. }
  63. for i := 0; i < cols; i++ {
  64. if len(pk[i]) != rows {
  65. if DEBUGGING_MODE {
  66. fmt.Printf("RingCT MLSAG_Ver pk matrix not rectangular\n")
  67. }
  68. result = false
  69. return
  70. }
  71. }
  72. if len(rv.II) != dsRows {
  73. if DEBUGGING_MODE {
  74. fmt.Printf("RingCT MLSAG_Ver Bad II size\n")
  75. }
  76. result = false
  77. return
  78. }
  79. if len(rv.ss) != cols {
  80. if DEBUGGING_MODE {
  81. fmt.Printf("RingCT MLSAG_Ver Bad rv.ss size len(rv.ss) = %d cols = %d\n", len(rv.ss), cols)
  82. }
  83. result = false
  84. return
  85. }
  86. for i := 0; i < cols; i++ {
  87. if len(rv.ss[i]) != rows {
  88. if DEBUGGING_MODE {
  89. fmt.Printf("RingCT MLSAG_Ver rv.ss is not rectangular\n")
  90. }
  91. result = false
  92. return
  93. }
  94. }
  95. if dsRows > rows {
  96. if DEBUGGING_MODE {
  97. fmt.Printf("RingCT MLSAG_Ver Bad dsRows value\n")
  98. }
  99. result = false
  100. return
  101. }
  102. for i := 0; i < len(rv.ss); i++ {
  103. for j := 0; j < len(rv.ss[i]); j++ {
  104. if !ScValid(&rv.ss[i][j]) {
  105. if DEBUGGING_MODE {
  106. fmt.Printf("RingCT MLSAG_Ver Bad ss slot\n")
  107. }
  108. result = false
  109. return
  110. }
  111. }
  112. }
  113. if !ScValid(&rv.cc) {
  114. if DEBUGGING_MODE {
  115. fmt.Printf("RingCT MLSAG_Ver Bad r.cc slot\n")
  116. }
  117. result = false
  118. return
  119. }
  120. Ip := make([][8]CachedGroupElement, dsRows, dsRows) // do pre computation of key keyImage
  121. for i := 0; i < dsRows; i++ {
  122. key_image_point := new(ExtendedGroupElement)
  123. key_image_point.FromBytes(&rv.II[i])
  124. GePrecompute(&Ip[i], key_image_point)
  125. }
  126. ndsRows := 3 * dsRows //non Double Spendable Rows (see identity chains paper
  127. toHash := make([]Key, 1+3*dsRows+2*(rows-dsRows), 1+3*dsRows+2*(rows-dsRows))
  128. toHash[0] = message
  129. // golang does NOT allow to use casts without using unsafe, so we can be slow but safe
  130. toHash_bytes := make([]byte, 0, (1+3*dsRows+2*(rows-dsRows))*len(message))
  131. var c Key
  132. c_old := rv.cc
  133. for i := 0; i < cols; i++ {
  134. Sc_0(&c) // zero out c
  135. // BUG BUG BUG
  136. // DERO project has found a go bug
  137. // This bug affects all known golang supported platforms and architectures (arm/386/amd64/...?)
  138. // even the golang 1.10 release candidates are affected ( though tip has not been tested )
  139. //
  140. // if you comment the line below and uncomment similiar line in first loop, the bug triggers for 1 in 20000 RCT full transactions, this means the the entire block chain cannot be verified before the bug fails the crypto
  141. // this bug triggers at high probability when the affected code is executed by multiple goroutines simultaneously
  142. // since the bug is notoriously hard to trigger while execution
  143. // we have figured out an easy way to visibly demonstrate that the bug is present
  144. // if the variables are declared within first loop, second loop is able to access them without declaring them
  145. // this causes random memory to be used during CPU load, causing the transaction to fail since crypto checksums mark it as failure ( TODO detailed analysis)
  146. // this bug may be the source of several other random crash bugs and need to be given a detailed looked
  147. // this may be the source of the follown known but not-understood (cause not found) bugs
  148. // https://github.com/golang/go/issues/15658
  149. // https://github.com/golang/go/issues/20427
  150. // https://github.com/golang/go/issues/22988
  151. // https://github.com/golang/go/issues/20300 and even more
  152. // NOTE: for golang developers, this bug needs to studied and fixed correctly. Since, another bug seems to exists
  153. // which causes constants to flip ( yes consts ). However, we cannot be certain if its the same bug, once this gets quashed, we will test the other one too.
  154. var L, R, Hi Key // comment this line and uncomment similiar line in first loop to trigger BUG
  155. // first loop
  156. for j := 0; j < dsRows; j++ {
  157. //var L, R, Hi Key // uncomment this line to trigger golang compiler BUG ( atleast on linux amd64)
  158. AddKeys2(&L, &rv.ss[i][j], &c_old, &pk[i][j])
  159. Hi = pk[i][j].HashToPoint()
  160. AddKeys3(&R, &rv.ss[i][j], &Hi, &c_old, &Ip[j])
  161. toHash[3*j+1] = pk[i][j]
  162. toHash[3*j+2] = L
  163. toHash[3*j+3] = R
  164. }
  165. //second loop
  166. for j, ii := dsRows, 0; j < rows; j, ii = j+1, ii+1 {
  167. AddKeys2(&L, &rv.ss[i][j], &c_old, &pk[i][j]) // here L is getting used again
  168. toHash[ndsRows+2*ii+1] = pk[i][j]
  169. toHash[ndsRows+2*ii+2] = L
  170. }
  171. toHash_bytes = toHash_bytes[:0] // zero out everything
  172. for k := range toHash {
  173. toHash_bytes = append(toHash_bytes, toHash[k][:]...)
  174. }
  175. c = *(HashToScalar(toHash_bytes)) // hash_to_scalar(toHash);
  176. copy(c_old[:], c[:]) // flipping the args here, will cause all transactions to become valid
  177. }
  178. if DEBUGGING_MODE {
  179. //fmt.Printf("c %x\n",c)
  180. fmt.Printf("c_old %s\n", c_old)
  181. fmt.Printf("rv.ss %s\n", rv.cc)
  182. }
  183. // c = c_old-rv.cc
  184. ScSub(&c, &c_old, &rv.cc)
  185. // if 0 checksum verified, otherwise checksum failed
  186. result = ScIsZero(&c)
  187. if DEBUGGING_MODE {
  188. if result {
  189. fmt.Printf("RingCT MLSAG_Ver Success\n")
  190. } else {
  191. fmt.Printf("RingCT MLSAG_Ver verification failed\n")
  192. }
  193. }
  194. return
  195. }