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.

357 lines
8.1 KiB

  1. package ringct
  2. import "io"
  3. import "fmt"
  4. import "github.com/deroproject/derosuite/crypto"
  5. // TODO this package need serious love of atleast few weeks
  6. // but atleast the parser and serdes works
  7. // we neeed to expand everthing so as chances of a bug slippping in becomes very low
  8. // NOTE:DO NOT waste time implmenting pre-RCT code
  9. const (
  10. RCTTypeNull = iota
  11. RCTTypeFull
  12. RCTTypeSimple
  13. )
  14. // Pedersen Commitment is generated from this struct
  15. // C = aG + bH where a = mask and b = amount
  16. // senderPk is the one-time public key for ECDH exchange
  17. type ecdhTuple struct {
  18. mask Key
  19. amount Key
  20. senderPk Key
  21. }
  22. // Range proof commitments
  23. type Key64 [64]Key
  24. // Range Signature
  25. // Essentially data for a Borromean Signature
  26. type RangeSig struct {
  27. asig BoroSig
  28. ci Key64
  29. }
  30. // Borromean Signature
  31. type BoroSig struct {
  32. s0 Key64
  33. s1 Key64
  34. ee Key
  35. }
  36. // MLSAG (Multilayered Linkable Spontaneous Anonymous Group) Signature
  37. type MlsagSig struct {
  38. ss [][]Key
  39. cc Key // this stores the starting point
  40. II []Key // this stores the keyimage, but is taken from the tx,it is NOT serialized
  41. }
  42. // Confidential Transaction Keys, mask is Pedersen Commitment
  43. // most of the time, it holds public keys, except where it holds private keys
  44. type CtKey struct {
  45. Destination Key // this is the destination and needs to expanded from blockchain
  46. Mask Key // this is the public key mask
  47. }
  48. // Ring Confidential Signature parts that we have to keep
  49. type RctSigBase struct {
  50. sigType uint8
  51. Message Key // transaction prefix hash
  52. MixRing [][]CtKey // this is not serialized
  53. pseudoOuts []Key
  54. ecdhInfo []ecdhTuple
  55. outPk []CtKey // only mask amount is serialized
  56. txFee uint64
  57. Txid crypto.Hash // this field is extra and only used for logging purposes to track which txid was at fault
  58. }
  59. // Ring Confidential Signature parts that we can just prune later
  60. type RctSigPrunable struct {
  61. rangeSigs []RangeSig
  62. MlsagSigs []MlsagSig
  63. }
  64. // Ring Confidential Signature struct that can verify everything
  65. type RctSig struct {
  66. RctSigBase
  67. RctSigPrunable
  68. }
  69. func (k *Key64) Serialize() (result []byte) {
  70. for _, key := range k {
  71. result = append(result, key[:]...)
  72. }
  73. return
  74. }
  75. func (b *BoroSig) Serialize() (result []byte) {
  76. result = append(b.s0.Serialize(), b.s1.Serialize()...)
  77. result = append(result, b.ee[:]...)
  78. return
  79. }
  80. func (r *RangeSig) Serialize() (result []byte) {
  81. result = append(r.asig.Serialize(), r.ci.Serialize()...)
  82. return
  83. }
  84. func (m *MlsagSig) Serialize() (result []byte) {
  85. for i := 0; i < len(m.ss); i++ {
  86. for j := 0; j < len(m.ss[i]); j++ {
  87. result = append(result, m.ss[i][j][:]...)
  88. }
  89. }
  90. result = append(result, m.cc[:]...)
  91. return
  92. }
  93. func (r *RctSigBase) SerializeBase() (result []byte) {
  94. result = []byte{r.sigType}
  95. // Null type returns right away
  96. if r.sigType == RCTTypeNull {
  97. return
  98. }
  99. result = append(result, Uint64ToBytes(r.txFee)...)
  100. if r.sigType == RCTTypeSimple {
  101. for _, input := range r.pseudoOuts {
  102. result = append(result, input[:]...)
  103. }
  104. }
  105. for _, ecdh := range r.ecdhInfo {
  106. result = append(result, ecdh.mask[:]...)
  107. result = append(result, ecdh.amount[:]...)
  108. }
  109. for _, ctKey := range r.outPk {
  110. result = append(result, ctKey.Mask[:]...)
  111. }
  112. return
  113. }
  114. func (r *RctSigBase) BaseHash() (result crypto.Hash) {
  115. result = crypto.Keccak256(r.SerializeBase())
  116. return
  117. }
  118. func (r *RctSig) SerializePrunable() (result []byte) {
  119. if r.sigType == RCTTypeNull {
  120. return
  121. }
  122. for _, rangeSig := range r.rangeSigs {
  123. result = append(result, rangeSig.Serialize()...)
  124. }
  125. for _, mlsagSig := range r.MlsagSigs {
  126. result = append(result, mlsagSig.Serialize()...)
  127. }
  128. return
  129. }
  130. func (r *RctSig) Get_Sig_Type() (byte) {
  131. return r.sigType
  132. }
  133. func (r *RctSig) Get_TX_Fee() (result uint64) {
  134. if r.sigType == RCTTypeNull {
  135. panic("RCTTypeNull cannot have TX fee")
  136. }
  137. return r.txFee
  138. }
  139. func (r *RctSig) PrunableHash() (result crypto.Hash) {
  140. if r.sigType == RCTTypeNull {
  141. return
  142. }
  143. result = crypto.Keccak256(r.SerializePrunable())
  144. return
  145. }
  146. // this is the function which should be used by external world
  147. func (r *RctSig) Verify() (result bool) {
  148. result = false
  149. defer func() { // safety so if anything wrong happens, verification fails
  150. if r := recover(); r != nil {
  151. //connection.logger.Fatalf("Recovered while Verify transaction", r)
  152. fmt.Printf("Recovered while Verify transaction")
  153. result = false
  154. }}()
  155. switch r.sigType {
  156. case RCTTypeNull: return true /// this is only possible for miner tx
  157. case RCTTypeFull : return r.VerifyRctFull()
  158. case RCTTypeSimple: return r.VerifyRctSimple()
  159. default :
  160. return false
  161. }
  162. return false
  163. }
  164. // Verify a RCTTypeSimple RingCT Signature
  165. func (r *RctSig) VerifyRctSimple() bool {
  166. sumOutPks := identity()
  167. for _, ctKey := range r.outPk {
  168. AddKeys(sumOutPks, sumOutPks, &ctKey.Mask)
  169. }
  170. txFeeKey := ScalarMultH(d2h(r.txFee))
  171. AddKeys(sumOutPks, sumOutPks, txFeeKey)
  172. sumPseudoOuts := identity()
  173. for _, pseudoOut := range r.pseudoOuts {
  174. AddKeys(sumPseudoOuts, sumPseudoOuts, &pseudoOut)
  175. }
  176. if *sumPseudoOuts != *sumOutPks {
  177. return false
  178. }
  179. for i, ctKey := range r.outPk {
  180. if !VerifyRange(&ctKey.Mask, r.rangeSigs[i]) {
  181. return false
  182. }
  183. }
  184. // BUG BUG we are not verifying mlsag here, Do it once the core finishes
  185. return true
  186. }
  187. func (r *RctSig) VerifyRctFull() bool {
  188. for i, ctKey := range r.outPk {
  189. if !VerifyRange(&ctKey.Mask, r.rangeSigs[i]) {
  190. return false
  191. }
  192. }
  193. // BUG BUG we are not verifying mlsag here, Do it once the core is finished
  194. return true
  195. }
  196. func ParseCtKey(buf io.Reader) (result CtKey, err error) {
  197. if result.Mask, err = ParseKey(buf); err != nil {
  198. return
  199. }
  200. return
  201. }
  202. func ParseKey64(buf io.Reader) (result Key64, err error) {
  203. for i := 0; i < 64; i++ {
  204. if result[i], err = ParseKey(buf); err != nil {
  205. return
  206. }
  207. }
  208. return
  209. }
  210. // parse Borromean signature
  211. func ParseBoroSig(buf io.Reader) (result BoroSig, err error) {
  212. if result.s0, err = ParseKey64(buf); err != nil {
  213. return
  214. }
  215. if result.s1, err = ParseKey64(buf); err != nil {
  216. return
  217. }
  218. if result.ee, err = ParseKey(buf); err != nil {
  219. return
  220. }
  221. return
  222. }
  223. // range data consists of Single Borromean sig and 64 keys for 64 bits
  224. func ParseRangeSig(buf io.Reader) (result RangeSig, err error) {
  225. if result.asig, err = ParseBoroSig(buf); err != nil {
  226. return
  227. }
  228. if result.ci, err = ParseKey64(buf); err != nil {
  229. return
  230. }
  231. return
  232. }
  233. // parser for ringct signature
  234. // we need to be extra cautious as almost anything cam come as input
  235. func ParseRingCtSignature(buf io.Reader, nInputs, nOutputs, nMixin int) (result *RctSig, err error) {
  236. r := new(RctSig)
  237. sigType := make([]byte, 1)
  238. _, err = buf.Read(sigType)
  239. if err != nil {
  240. return
  241. }
  242. r.sigType = uint8(sigType[0])
  243. if r.sigType == RCTTypeNull {
  244. result = r
  245. return
  246. }
  247. if r.sigType != RCTTypeFull || r.sigType != RCTTypeSimple {
  248. err = fmt.Errorf("Bad signature Type %d", r.sigType)
  249. }
  250. r.txFee, err = ReadVarInt(buf)
  251. if err != nil {
  252. return
  253. }
  254. var nMg, nSS int
  255. if r.sigType == RCTTypeSimple {
  256. nMg = nInputs
  257. nSS = 2
  258. r.pseudoOuts = make([]Key, nInputs)
  259. for i := 0; i < nInputs; i++ {
  260. if r.pseudoOuts[i], err = ParseKey(buf); err != nil {
  261. return
  262. }
  263. }
  264. } else {
  265. nMg = 1
  266. nSS = nInputs + 1
  267. }
  268. r.ecdhInfo = make([]ecdhTuple, nOutputs)
  269. for i := 0; i < nOutputs; i++ {
  270. if r.ecdhInfo[i].mask, err = ParseKey(buf); err != nil {
  271. return
  272. }
  273. if r.ecdhInfo[i].amount, err = ParseKey(buf); err != nil {
  274. return
  275. }
  276. }
  277. r.outPk = make([]CtKey, nOutputs)
  278. for i := 0; i < nOutputs; i++ {
  279. if r.outPk[i], err = ParseCtKey(buf); err != nil {
  280. return
  281. }
  282. }
  283. r.rangeSigs = make([]RangeSig, nOutputs)
  284. for i := 0; i < nOutputs; i++ {
  285. if r.rangeSigs[i], err = ParseRangeSig(buf); err != nil {
  286. return
  287. }
  288. }
  289. r.MlsagSigs = make([]MlsagSig, nMg)
  290. for i := 0; i < nMg; i++ {
  291. r.MlsagSigs[i].ss = make([][]Key, nMixin+1)
  292. for j := 0; j < nMixin+1; j++ {
  293. r.MlsagSigs[i].ss[j] = make([]Key, nSS)
  294. for k := 0; k < nSS; k++ {
  295. if r.MlsagSigs[i].ss[j][k], err = ParseKey(buf); err != nil {
  296. return
  297. }
  298. }
  299. }
  300. if r.MlsagSigs[i].cc, err = ParseKey(buf); err != nil {
  301. return
  302. }
  303. }
  304. result = r
  305. return
  306. }