Dero Web Wallet derosuite. This repo contains changes required for webwallet. With this changes any Dero daemon can become web wallet. All changes are related to daemon rpc server and wallet to make it light and faster.
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.

172 lines
5.3KB

  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 address
  17. import "fmt"
  18. import "bytes"
  19. import "encoding/binary"
  20. import "github.com/deroproject/derosuite/config"
  21. import "github.com/deroproject/derosuite/crypto"
  22. // see https://cryptonote.org/cns/cns007.txt to understand address more
  23. type Address struct {
  24. Network uint64
  25. SpendKey crypto.Key // these are public keys only
  26. ViewKey crypto.Key // these are public keys only
  27. PaymentID []byte //integrated payment id is 8 bytes
  28. // 8 byte version is encrypted on the blockchain
  29. // 32 byte version is dumped on the chain openly
  30. }
  31. const ChecksumLength = 4
  32. type Checksum [ChecksumLength]byte
  33. func GetChecksum(data ...[]byte) (result Checksum) {
  34. keccak256 := crypto.Keccak256(data...)
  35. copy(result[:], keccak256[:4])
  36. return
  37. }
  38. func (a *Address) Base58() (result string) {
  39. prefix := make([]byte, 9, 9)
  40. n := binary.PutUvarint(prefix, a.Network)
  41. prefix = prefix[:n]
  42. // convert address to string ( include payment ID if prefix says so )
  43. switch a.Network {
  44. case 19:
  45. fallthrough // for testing purpose monero integrated address
  46. case config.Mainnet.Public_Address_Prefix_Integrated:
  47. fallthrough
  48. case config.Testnet.Public_Address_Prefix_Integrated:
  49. checksum := GetChecksum(prefix, a.SpendKey[:], a.ViewKey[:], a.PaymentID)
  50. result = EncodeDeroBase58(prefix, a.SpendKey[:], a.ViewKey[:], a.PaymentID, checksum[:])
  51. // normal addresses without prefix
  52. case config.Mainnet.Public_Address_Prefix:
  53. fallthrough
  54. case config.Testnet.Public_Address_Prefix:
  55. fallthrough
  56. default:
  57. checksum := GetChecksum(prefix, a.SpendKey[:], a.ViewKey[:])
  58. result = EncodeDeroBase58(prefix, a.SpendKey[:], a.ViewKey[:], checksum[:])
  59. }
  60. return
  61. }
  62. // stringifier
  63. func (a Address) String() string {
  64. return a.Base58()
  65. }
  66. // tells whether address is mainnet address
  67. func (a *Address) IsMainnet() bool {
  68. if a.Network == config.Mainnet.Public_Address_Prefix ||
  69. a.Network == config.Mainnet.Public_Address_Prefix_Integrated {
  70. return true
  71. }
  72. return false
  73. }
  74. // tells whether address is mainnet address
  75. func (a *Address) IsIntegratedAddress() bool {
  76. if a.Network == config.Testnet.Public_Address_Prefix_Integrated ||
  77. a.Network == config.Mainnet.Public_Address_Prefix_Integrated {
  78. return true
  79. }
  80. return false
  81. }
  82. // tells whether address belongs to DERO Network
  83. func (a *Address) IsDERONetwork() bool {
  84. if a.Network == config.Mainnet.Public_Address_Prefix ||
  85. a.Network == config.Mainnet.Public_Address_Prefix_Integrated ||
  86. a.Network == config.Testnet.Public_Address_Prefix ||
  87. a.Network == config.Testnet.Public_Address_Prefix_Integrated {
  88. return true
  89. }
  90. return false
  91. }
  92. func NewAddress(address string) (result *Address, err error) {
  93. raw := DecodeDeroBase58(address)
  94. // donot compare length to support much more user base and be compatible with cryptonote
  95. if len(raw) < 69 { // 1 byte prefix + 32 byte key + 32 byte key + 4 byte checksum
  96. err = fmt.Errorf("Address is not complete")
  97. return
  98. }
  99. checksum := GetChecksum(raw[:len(raw)-4])
  100. if bytes.Compare(checksum[:], raw[len(raw)-4:]) != 0 {
  101. err = fmt.Errorf("Checksum failed")
  102. return
  103. }
  104. raw = raw[0 : len(raw)-4] // remove the checksum
  105. // parse network first
  106. address_prefix, done := binary.Uvarint(raw)
  107. if done <= 0 {
  108. err = fmt.Errorf("Network could not be parsed in address\n")
  109. return
  110. }
  111. raw = raw[done:]
  112. result = &Address{
  113. Network: address_prefix,
  114. //SpendKey: raw[0:32],
  115. //ViewKey: raw[32:64],
  116. }
  117. copy(result.SpendKey[:], raw[0:32])
  118. copy(result.ViewKey[:], raw[32:64])
  119. //
  120. switch address_prefix { // if network id is integrated address
  121. case 19:
  122. fallthrough //Monero_MainNetwork_Integrated: for testing purposes only for compatible reasons
  123. case config.Mainnet.Public_Address_Prefix_Integrated:
  124. fallthrough // DERO mainnet integrated address
  125. case config.Testnet.Public_Address_Prefix_Integrated: // DERO testnet integrated address
  126. if len(raw[64:]) == 8 { // 8 byte encrypted payment id + 4 bytes
  127. result.PaymentID = raw[64:]
  128. } else if len(raw[64:]) == 32 { // 32 byte unencrypted payment ID
  129. result.PaymentID = raw[64:]
  130. } else {
  131. err = fmt.Errorf("Invalid payment ID in address\n")
  132. return
  133. }
  134. }
  135. return
  136. }
  137. // create a new address from keys
  138. func NewAddressFromKeys(spendkey, viewkey crypto.Key) (result *Address) {
  139. result = &Address{
  140. Network: config.Mainnet.Public_Address_Prefix,
  141. SpendKey: spendkey,
  142. ViewKey: viewkey,
  143. }
  144. return
  145. }