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.

445 lines
12 KiB

  1. // Copyright 2017-2018 DERO Project. All rights reserved.
  2. // Use of this source code in any form is governed by RESEARCH license.
  3. // license can be found in the LICENSE file.
  4. // GPG: 0F39 E425 8C65 3947 702A 8234 08B2 0360 A03A 9DE8
  5. //
  6. //
  7. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
  8. // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  9. // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  10. // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  11. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  12. // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  13. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  14. // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  15. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  16. package ringct
  17. import "io"
  18. import "fmt"
  19. import "github.com/arnaucode/derosuite/crypto"
  20. // enable debuggin mode within ringct
  21. // if true debugging mode enabled
  22. const DEBUGGING_MODE = false
  23. // TODO this package need serious love of atleast few weeks
  24. // but atleast the parser and serdes works
  25. // we neeed to expand everthing so as chances of a bug slippping in becomes very low
  26. // NOTE:DO NOT waste time implmenting pre-RCT code
  27. const (
  28. RCTTypeNull = iota
  29. RCTTypeFull
  30. RCTTypeSimple
  31. )
  32. // Pedersen Commitment is generated from this struct
  33. // C = aG + bH where a = mask and b = amount
  34. // senderPk is the one-time public key for ECDH exchange
  35. type ECdhTuple struct {
  36. Mask Key `msgpack:"M"`
  37. Amount Key `msgpack:"A"`
  38. // senderPk Key
  39. }
  40. // Range proof commitments
  41. type Key64 [64]Key
  42. // Range Signature
  43. // Essentially data for a Borromean Signature
  44. type RangeSig struct {
  45. asig BoroSig
  46. ci Key64
  47. }
  48. // Borromean Signature
  49. type BoroSig struct {
  50. s0 Key64
  51. s1 Key64
  52. ee Key
  53. }
  54. // MLSAG (Multilayered Linkable Spontaneous Anonymous Group) Signature
  55. type MlsagSig struct {
  56. ss [][]Key
  57. cc Key // this stores the starting point
  58. II []Key // this stores the keyimage, but is taken from the tx,it is NOT serialized
  59. }
  60. // Confidential Transaction Keys, mask is Pedersen Commitment
  61. // most of the time, it holds public keys, except (transaction making ) where it holds private keys
  62. type CtKey struct {
  63. Destination Key `msgpack:"D"` // this is the destination and needs to expanded from blockchain
  64. Mask Key `msgpack:"M"` // this is the public key amount/commitment homomorphic mask
  65. }
  66. // Ring Confidential Signature parts that we have to keep
  67. type RctSigBase struct {
  68. sigType uint8
  69. Message Key // transaction prefix hash
  70. MixRing [][]CtKey // this is not serialized
  71. pseudoOuts []Key
  72. ECdhInfo []ECdhTuple
  73. OutPk []CtKey // only mask amount is serialized
  74. txFee uint64
  75. Txid crypto.Hash // this field is extra and only used for logging purposes to track which txid was at fault
  76. }
  77. // Ring Confidential Signature parts that we can just prune later
  78. type RctSigPrunable struct {
  79. rangeSigs []RangeSig
  80. MlsagSigs []MlsagSig // there can be as many mlsagsigs as many vins
  81. }
  82. // Ring Confidential Signature struct that can verify everything
  83. type RctSig struct {
  84. RctSigBase
  85. RctSigPrunable
  86. }
  87. func (k *Key64) Serialize() (result []byte) {
  88. for _, key := range k {
  89. result = append(result, key[:]...)
  90. }
  91. return
  92. }
  93. func (b *BoroSig) Serialize() (result []byte) {
  94. result = append(b.s0.Serialize(), b.s1.Serialize()...)
  95. result = append(result, b.ee[:]...)
  96. return
  97. }
  98. func (r *RangeSig) Serialize() (result []byte) {
  99. result = append(r.asig.Serialize(), r.ci.Serialize()...)
  100. return
  101. }
  102. func (m *MlsagSig) Serialize() (result []byte) {
  103. for i := 0; i < len(m.ss); i++ {
  104. for j := 0; j < len(m.ss[i]); j++ {
  105. result = append(result, m.ss[i][j][:]...)
  106. }
  107. }
  108. result = append(result, m.cc[:]...)
  109. return
  110. }
  111. func (r *RctSigBase) SerializeBase() (result []byte) {
  112. result = []byte{r.sigType}
  113. // Null type returns right away
  114. if r.sigType == RCTTypeNull {
  115. return
  116. }
  117. result = append(result, Uint64ToBytes(r.txFee)...)
  118. if r.sigType == RCTTypeSimple {
  119. for _, input := range r.pseudoOuts {
  120. result = append(result, input[:]...)
  121. }
  122. }
  123. for _, ecdh := range r.ECdhInfo {
  124. result = append(result, ecdh.Mask[:]...)
  125. result = append(result, ecdh.Amount[:]...)
  126. }
  127. for _, ctKey := range r.OutPk {
  128. result = append(result, ctKey.Mask[:]...)
  129. }
  130. return
  131. }
  132. func (r *RctSigBase) BaseHash() (result crypto.Hash) {
  133. result = crypto.Keccak256(r.SerializeBase())
  134. return
  135. }
  136. func (r *RctSig) SerializePrunable() (result []byte) {
  137. if r.sigType == RCTTypeNull {
  138. return
  139. }
  140. for _, rangeSig := range r.rangeSigs {
  141. result = append(result, rangeSig.Serialize()...)
  142. }
  143. for _, mlsagSig := range r.MlsagSigs {
  144. result = append(result, mlsagSig.Serialize()...)
  145. }
  146. return
  147. }
  148. func (r *RctSig) Get_Sig_Type() byte {
  149. return r.sigType
  150. }
  151. func (r *RctSig) Get_TX_Fee() (result uint64) {
  152. if r.sigType == RCTTypeNull {
  153. panic("RCTTypeNull cannot have TX fee")
  154. }
  155. return r.txFee
  156. }
  157. func (r *RctSig) PrunableHash() (result crypto.Hash) {
  158. if r.sigType == RCTTypeNull {
  159. return
  160. }
  161. result = crypto.Keccak256(r.SerializePrunable())
  162. return
  163. }
  164. // this is the function which should be used by external world
  165. // if any exceptions occur while handling, we simply return false
  166. // transaction must be expanded before verification
  167. // coinbase transactions are always success, since they are tied to PoW of block
  168. func (r *RctSig) Verify() (result bool) {
  169. result = false
  170. defer func() { // safety so if anything wrong happens, verification fails
  171. if r := recover(); r != nil {
  172. //connection.logger.Fatalf("Recovered while Verify transaction", r)
  173. fmt.Printf("Recovered while Verify transaction")
  174. result = false
  175. }
  176. }()
  177. switch r.sigType {
  178. case RCTTypeNull:
  179. return true /// this is only possible for miner tx
  180. case RCTTypeFull:
  181. return r.VerifyRctFull()
  182. case RCTTypeSimple:
  183. return r.VerifyRctSimple()
  184. default:
  185. return false
  186. }
  187. // can never reach here
  188. // return false
  189. }
  190. // Verify a RCTTypeSimple RingCT Signature
  191. func (r *RctSig) VerifyRctSimple() bool {
  192. sumOutPks := identity()
  193. for _, ctKey := range r.OutPk {
  194. AddKeys(sumOutPks, sumOutPks, &ctKey.Mask)
  195. }
  196. //txFeeKey := ScalarMultH(d2h(r.txFee))
  197. txFeeKey := Commitment_From_Amount(r.txFee)
  198. AddKeys(sumOutPks, sumOutPks, &txFeeKey)
  199. sumPseudoOuts := identity()
  200. for _, pseudoOut := range r.pseudoOuts {
  201. AddKeys(sumPseudoOuts, sumPseudoOuts, &pseudoOut)
  202. }
  203. if *sumPseudoOuts != *sumOutPks {
  204. return false
  205. }
  206. for i, ctKey := range r.OutPk {
  207. if !VerifyRange(&ctKey.Mask, r.rangeSigs[i]) {
  208. return false
  209. }
  210. }
  211. return r.VerifyRCTSimple_Core()
  212. }
  213. func (r *RctSig) VerifyRctFull() bool {
  214. for i, ctKey := range r.OutPk {
  215. if !VerifyRange(&ctKey.Mask, r.rangeSigs[i]) {
  216. return false
  217. }
  218. }
  219. return r.VerifyRCTFull_Core()
  220. }
  221. func ParseCtKey(buf io.Reader) (result CtKey, err error) {
  222. if result.Mask, err = ParseKey(buf); err != nil {
  223. return
  224. }
  225. return
  226. }
  227. func ParseKey64(buf io.Reader) (result Key64, err error) {
  228. for i := 0; i < 64; i++ {
  229. if result[i], err = ParseKey(buf); err != nil {
  230. return
  231. }
  232. }
  233. return
  234. }
  235. // parse Borromean signature
  236. func ParseBoroSig(buf io.Reader) (result BoroSig, err error) {
  237. if result.s0, err = ParseKey64(buf); err != nil {
  238. return
  239. }
  240. if result.s1, err = ParseKey64(buf); err != nil {
  241. return
  242. }
  243. if result.ee, err = ParseKey(buf); err != nil {
  244. return
  245. }
  246. return
  247. }
  248. // range data consists of Single Borromean sig and 64 keys for 64 bits
  249. func ParseRangeSig(buf io.Reader) (result RangeSig, err error) {
  250. if result.asig, err = ParseBoroSig(buf); err != nil {
  251. return
  252. }
  253. if result.ci, err = ParseKey64(buf); err != nil {
  254. return
  255. }
  256. return
  257. }
  258. // parser for ringct signature
  259. // we need to be extra cautious as almost anything cam come as input
  260. func ParseRingCtSignature(buf io.Reader, nInputs, nOutputs, nMixin int) (result *RctSig, err error) {
  261. r := new(RctSig)
  262. sigType := make([]byte, 1)
  263. _, err = buf.Read(sigType)
  264. if err != nil {
  265. return
  266. }
  267. r.sigType = uint8(sigType[0])
  268. if r.sigType == RCTTypeNull {
  269. result = r
  270. return
  271. }
  272. /* This triggers go vet saying suspect OR
  273. if (r.sigType != RCTTypeFull) || (r.sigType != RCTTypeSimple) {
  274. err = fmt.Errorf("Bad signature Type %d", r.sigType)
  275. return
  276. }*/
  277. switch r.sigType {
  278. case RCTTypeFull:
  279. case RCTTypeSimple:
  280. default:
  281. err = fmt.Errorf("Bad signature Type %d", r.sigType)
  282. return
  283. }
  284. r.txFee, err = ReadVarInt(buf)
  285. if err != nil {
  286. return
  287. }
  288. var nMg, nSS int
  289. if r.sigType == RCTTypeSimple {
  290. nMg = nInputs
  291. nSS = 2
  292. r.pseudoOuts = make([]Key, nInputs)
  293. for i := 0; i < nInputs; i++ {
  294. if r.pseudoOuts[i], err = ParseKey(buf); err != nil {
  295. return
  296. }
  297. }
  298. } else {
  299. nMg = 1
  300. nSS = nInputs + 1
  301. }
  302. r.ECdhInfo = make([]ECdhTuple, nOutputs)
  303. for i := 0; i < nOutputs; i++ {
  304. if r.ECdhInfo[i].Mask, err = ParseKey(buf); err != nil {
  305. return
  306. }
  307. if r.ECdhInfo[i].Amount, err = ParseKey(buf); err != nil {
  308. return
  309. }
  310. }
  311. r.OutPk = make([]CtKey, nOutputs)
  312. for i := 0; i < nOutputs; i++ {
  313. if r.OutPk[i], err = ParseCtKey(buf); err != nil {
  314. return
  315. }
  316. }
  317. r.rangeSigs = make([]RangeSig, nOutputs)
  318. for i := 0; i < nOutputs; i++ {
  319. if r.rangeSigs[i], err = ParseRangeSig(buf); err != nil {
  320. return
  321. }
  322. }
  323. r.MlsagSigs = make([]MlsagSig, nMg)
  324. for i := 0; i < nMg; i++ {
  325. r.MlsagSigs[i].ss = make([][]Key, nMixin+1)
  326. for j := 0; j < nMixin+1; j++ {
  327. r.MlsagSigs[i].ss[j] = make([]Key, nSS)
  328. for k := 0; k < nSS; k++ {
  329. if r.MlsagSigs[i].ss[j][k], err = ParseKey(buf); err != nil {
  330. return
  331. }
  332. }
  333. }
  334. if r.MlsagSigs[i].cc, err = ParseKey(buf); err != nil {
  335. return
  336. }
  337. }
  338. result = r
  339. return
  340. }
  341. /*
  342. //Elliptic Curve Diffie Helman: encodes and decodes the amount b and mask a
  343. // where C= aG + bH
  344. void ecdhEncode(ecdhTuple & unmasked, const key & sharedSec) {
  345. key sharedSec1 = hash_to_scalar(sharedSec);
  346. key sharedSec2 = hash_to_scalar(sharedSec1);
  347. //encode
  348. sc_add(unmasked.mask.bytes, unmasked.mask.bytes, sharedSec1.bytes);
  349. sc_add(unmasked.amount.bytes, unmasked.amount.bytes, sharedSec2.bytes);
  350. }
  351. void ecdhDecode(ecdhTuple & masked, const key & sharedSec) {
  352. key sharedSec1 = hash_to_scalar(sharedSec);
  353. key sharedSec2 = hash_to_scalar(sharedSec1);
  354. //decode
  355. sc_sub(masked.mask.bytes, masked.mask.bytes, sharedSec1.bytes);
  356. sc_sub(masked.amount.bytes, masked.amount.bytes, sharedSec2.bytes);
  357. }
  358. */
  359. func ecdhEncode(tuple *ECdhTuple, shared_secret Key) {
  360. shared_secret1 := HashToScalar(shared_secret[:])
  361. shared_secret2 := HashToScalar(shared_secret1[:])
  362. // encode
  363. ScAdd(&tuple.Mask, &tuple.Mask, shared_secret1)
  364. ScAdd(&tuple.Amount, &tuple.Amount, shared_secret2)
  365. }
  366. func ecdhDecode(tuple *ECdhTuple, shared_secret Key) {
  367. shared_secret1 := HashToScalar(shared_secret[:])
  368. shared_secret2 := HashToScalar(shared_secret1[:])
  369. // encode
  370. ScSub(&tuple.Mask, &tuple.Mask, shared_secret1)
  371. ScSub(&tuple.Amount, &tuple.Amount, shared_secret2)
  372. }
  373. // decode and verify a previously encrypted tuple
  374. // the keys come in from the wallet
  375. // tuple is the encoded data
  376. // skey is the secret scalar key
  377. // outpk is public key used to verify whether the decode was sucessfull
  378. func Decode_Amount(tuple ECdhTuple, skey Key, outpk Key) (amount uint64, mask Key, result bool) {
  379. var Ctmp Key
  380. ecdhDecode(&tuple, skey) // decode the amounts
  381. // saniity check similiar to original one
  382. // addKeys2(Ctmp, mask, amount, H);
  383. AddKeys2(&Ctmp, &tuple.Mask, &tuple.Amount, &H)
  384. if Ctmp != outpk {
  385. fmt.Printf("warning, amount decoded incorrectly, will be unable to spend")
  386. result = false
  387. return
  388. }
  389. amount = h2d(tuple.Amount)
  390. mask = tuple.Mask
  391. result = true
  392. return
  393. }