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.

95 lines
2.7 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 address
  17. import "fmt"
  18. import "bytes"
  19. import "encoding/binary"
  20. import "github.com/arnaucode/derosuite/crypto"
  21. // see https://cryptonote.org/cns/cns007.txt to understand address more
  22. type Address struct {
  23. Network uint64
  24. SpendKey crypto.Key
  25. ViewKey crypto.Key
  26. //TODO add support for integrated address
  27. }
  28. const ChecksumLength = 4
  29. type Checksum [ChecksumLength]byte
  30. func GetChecksum(data ...[]byte) (result Checksum) {
  31. keccak256 := crypto.Keccak256(data...)
  32. copy(result[:], keccak256[:4])
  33. return
  34. }
  35. func (a *Address) Base58() (result string) {
  36. prefix := make([]byte, 9, 9)
  37. n := binary.PutUvarint(prefix, a.Network)
  38. prefix = prefix[:n]
  39. checksum := GetChecksum(prefix, a.SpendKey[:], a.ViewKey[:])
  40. result = EncodeDeroBase58(prefix, a.SpendKey[:], a.ViewKey[:], checksum[:])
  41. return
  42. }
  43. // stringifier
  44. func (a Address) String() string {
  45. return a.Base58()
  46. }
  47. func NewAddress(address string) (result *Address, err error) {
  48. raw := DecodeDeroBase58(address)
  49. // donot compare length to support much more user base and be compatible with cryptonote
  50. if len(raw) < 69 { // 1 byte prefix + 32 byte key + 32 byte key + 4 byte checksum
  51. err = fmt.Errorf("Address is the wrong length")
  52. return
  53. }
  54. checksum := GetChecksum(raw[:len(raw)-4])
  55. if bytes.Compare(checksum[:], raw[len(raw)-4:]) != 0 {
  56. err = fmt.Errorf("Checksum does not validate")
  57. return
  58. }
  59. // parse network first
  60. address_prefix, done := binary.Uvarint(raw)
  61. if done <= 0 {
  62. err = fmt.Errorf("Network could not be parsed in address\n")
  63. return
  64. }
  65. raw = raw[done:]
  66. result = &Address{
  67. Network: address_prefix,
  68. //SpendKey: raw[0:32],
  69. //ViewKey: raw[32:64],
  70. }
  71. copy(result.SpendKey[:], raw[0:32])
  72. copy(result.ViewKey[:], raw[32:64])
  73. return
  74. }