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.

124 lines
4.8KB

  1. package main
  2. import "fmt"
  3. import "flag"
  4. import "github.com/kubernetes/klog"
  5. import "github.com/clearmatics/bn256"
  6. const POINT_SIZE = 33 // this can be optimized to 33 bytes
  7. const FIELDELEMENT_SIZE = 32 // why not have bigger curves
  8. const RING_SIZE = 8 // use powers of 2, note this is not currently sanity checked
  9. // protocol supports amounts upto this, however this pre=alpha wallet supports only 65535 as we use bruteforce to decode balance
  10. const MAX_AMOUNT = 18446744073709551616 // 2^64 - 1,, current wallet supports amounts of only 65535 are supported
  11. const PROTOCOL_CONSTANT = "DERO"
  12. // as you can see overhead per account is 3 curve points, , user public key, 2 points for encrypted balances
  13. type Blockchain struct {
  14. registeredusers map[string]*bn256.G1 // registered users,, public key of user
  15. balances map[string]*Balance // encrypted balances of registered users
  16. }
  17. type Balance struct { // all balances are kept here and overhead of per account in blockchain is 66 bytes
  18. C [2]bn256.G1
  19. }
  20. func init() {
  21. klog.InitFlags(nil) // setup logging
  22. flag.Set("logtostderr", "true")
  23. flag.Set("stderrthreshold", "WARNING")
  24. flag.Set("v", "0") // set this to 1 or 2 to enable verbose logging
  25. flag.Parse()
  26. }
  27. func main() {
  28. fmt.Printf("\n\n DERO HOMOMORPHIC PROTOCOL ( pre-alpha version )\n\n")
  29. blockchain := init_blockchain() // init memory map based chain to validate concept
  30. sender := GenerateKeyPair()
  31. receiver := GenerateKeyPair()
  32. if err := blockchain.registerUser(sender); err != nil { // register sender
  33. panic(err)
  34. }
  35. if err := blockchain.registerUser(receiver); err != nil { // register receiver
  36. panic(err)
  37. }
  38. klog.V(0).Infof("sender \n%s\n", *sender)
  39. klog.V(0).Infof("receiver \n%s\n", *receiver)
  40. var dummies []*KeyPair // generate dummies to be used as anonymous groups
  41. for i := 0; i < 2100; i++ {
  42. dummies = append(dummies, GenerateKeyPair()) // generate a random user
  43. if err := blockchain.registerUser(dummies[i]); err != nil { // register a user
  44. panic(err)
  45. }
  46. }
  47. // this basicaly is a mining transaction, in this poc you can give any one any balance
  48. if err := blockchain.FundUser(sender.y, 150); err != nil { // sender now has balance 150
  49. panic(err)
  50. }
  51. // do 2 transfers, one of 10, other 90 with ring size 8 and 16 respectively
  52. blockchain.transfer(sender, receiver, 10, dummies, 8) // transfer 10 from sender to receiver ring size 8
  53. blockchain.transfer(sender, receiver, 90, dummies, 16) // transfer 90 from sender to receiver, ring size 16
  54. klog.V(0).Infof("\n\t\t\tSuccessful\n")
  55. }
  56. // wrap transfer in a function for better understanding of users
  57. func (blockchain *Blockchain) transfer(sender, receiver *KeyPair, amount uint32, dummies []*KeyPair, ring_size int) {
  58. defer func() {
  59. if r := recover(); r != nil {
  60. fmt.Println("Transfer failed ", r)
  61. }
  62. }()
  63. sender_balance_before_transfer, _ := blockchain.ReadBalance(sender.y, sender.x) // find balance via bruteforce
  64. receiver_balance_before_transfer, _ := blockchain.ReadBalance(receiver.y, receiver.x) // find balance via bruteforce
  65. var anonlist []*bn256.G1 // choose anonymous peers, this should be done carefully
  66. for i := 0; i < ring_size-2; i++ { // it must (2^n) -2 , example 2,6,14,30,62, 126,254,510,1022,2046 etc
  67. anonlist = append(anonlist, dummies[i].y)
  68. }
  69. transfer_amount := amount // total value to transfer
  70. klog.V(0).Infof("\n\nCreating Transaction")
  71. tx := blockchain.BuildTransaction(sender, receiver.y, transfer_amount, anonlist) // generate proof for sending value 10
  72. klog.V(0).Infof("Transferring %d from sender to receiver (ring size %d) tx size %d bytes ", transfer_amount, len(anonlist)+2, tx.Size())
  73. klog.V(0).Infof("Total tx size %d bytes ( %d byte statement, %d bytes proof ) ", tx.Size(), tx.statement.Size(), tx.proof.Size())
  74. // at this point tx has strong anonymity and deniablity and leak proof, you are welcome to analyse it for any leakages
  75. if blockchain.ExecuteTransaction(tx) {
  76. klog.V(0).Infof("Transfer successful")
  77. } else {
  78. klog.Fatalf("Transfer failed. please enable logs")
  79. return
  80. }
  81. sender_balance_after_transfer, _ := blockchain.ReadBalance(sender.y, sender.x) // find balance via bruteforce
  82. receiver_balance_after_transfer, _ := blockchain.ReadBalance(receiver.y, receiver.x) // find balance via bruteforce
  83. klog.V(0).Infof("%20s %9d - %9d = %9d\n", "Sender Balance", sender_balance_before_transfer, transfer_amount, sender_balance_after_transfer)
  84. klog.V(0).Infof("%20s %9d + %9d = %9d\n", "Receiver Balance", receiver_balance_before_transfer, transfer_amount, receiver_balance_after_transfer)
  85. if (sender_balance_before_transfer-transfer_amount) != sender_balance_after_transfer ||
  86. (receiver_balance_before_transfer+transfer_amount) != receiver_balance_after_transfer {
  87. panic("something failed.. jump in")
  88. }
  89. }