github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/entity_id.go (about)

     1  package hedera
     2  
     3  /*-
     4   *
     5   * Hedera Go SDK
     6   *
     7   * Copyright (C) 2020 - 2024 Hedera Hashgraph, LLC
     8   *
     9   * Licensed under the Apache License, Version 2.0 (the "License");
    10   * you may not use this file except in compliance with the License.
    11   * You may obtain a copy of the License at
    12   *
    13   *      http://www.apache.org/licenses/LICENSE-2.0
    14   *
    15   * Unless required by applicable law or agreed to in writing, software
    16   * distributed under the License is distributed on an "AS IS" BASIS,
    17   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    18   * See the License for the specific language governing permissions and
    19   * limitations under the License.
    20   *
    21   */
    22  
    23  import (
    24  	"fmt"
    25  	"regexp"
    26  	"strconv"
    27  
    28  	"github.com/pkg/errors"
    29  )
    30  
    31  // EntityID is an interface for various IDs of entities (Account, Contract, File, etc)
    32  type EntityID interface {
    33  	_IsEntityID()
    34  }
    35  
    36  type _ParseAddressResult struct {
    37  	status             int
    38  	num1               int64
    39  	num2               int64
    40  	num3               int64
    41  	correctChecksum    string
    42  	givenChecksum      string
    43  	noChecksumFormat   string
    44  	withChecksumFormat string
    45  }
    46  
    47  func _ChecksumVerify(num int) error {
    48  	switch num {
    49  	case 0:
    50  		return errors.New("Invalid ID: format should look like 0.0.123 or 0.0.123-laujm")
    51  	case 1:
    52  		return errors.New("Invalid ID: checksum does not match")
    53  	case 2:
    54  		return nil
    55  	case 3:
    56  		return nil
    57  	default:
    58  		return errors.New("Unrecognized status")
    59  	}
    60  }
    61  
    62  func _ChecksumParseAddress(ledgerID *LedgerID, address string) (_ParseAddressResult, error) {
    63  	var err error
    64  	match := regexp.MustCompile(`(0|(?:[1-9]\d*))\.(0|(?:[1-9]\d*))\.(0|(?:[1-9]\d*))(?:-([a-z]{5}))?$`)
    65  
    66  	matchArray := match.FindStringSubmatch(address)
    67  
    68  	a := make([]int64, len(matchArray))
    69  	for i := 1; i < len(matchArray)-1; i++ {
    70  		a[i], err = strconv.ParseInt(matchArray[i], 10, 64)
    71  		if err != nil {
    72  			return _ParseAddressResult{status: 0}, err
    73  		}
    74  	}
    75  
    76  	ad := fmt.Sprintf("%s.%s.%s", matchArray[1], matchArray[2], matchArray[3])
    77  
    78  	checksum := _CheckChecksum(ledgerID._LedgerIDBytes, ad)
    79  
    80  	var status int
    81  	switch m := matchArray[4]; {
    82  	case m == "":
    83  		status = 2
    84  	case m == checksum:
    85  		status = 3
    86  	default:
    87  		status = 1
    88  	}
    89  
    90  	return _ParseAddressResult{
    91  		status:             status,
    92  		num1:               a[1],
    93  		num2:               a[2],
    94  		num3:               a[3],
    95  		correctChecksum:    checksum,
    96  		givenChecksum:      matchArray[4],
    97  		noChecksumFormat:   ad,
    98  		withChecksumFormat: ad + "(" + checksum + ")",
    99  	}, nil
   100  }
   101  
   102  func _CheckChecksum(ledgerID []byte, address string) string {
   103  	answer := ""
   104  	digits := make([]int, 0)
   105  	s0 := 0
   106  	s1 := 0
   107  	s := 0
   108  	sh := 0
   109  	checksum := 0
   110  	n := len(address)
   111  	p3 := 26 * 26 * 26
   112  	p5 := 26 * 26 * 26 * 26 * 26
   113  	m := 1000003
   114  	asciiA := []rune("a")[0]
   115  	w := 31
   116  
   117  	h := make([]byte, len(ledgerID)+6)
   118  	copy(h[0:len(ledgerID)], ledgerID)
   119  
   120  	for _, j := range address {
   121  		if string(j) == "." {
   122  			digits = append(digits, 10)
   123  		} else {
   124  			processed, _ := strconv.Atoi(string(j))
   125  			digits = append(digits, processed)
   126  		}
   127  	}
   128  
   129  	for i := 0; i < len(digits); i++ {
   130  		s = (w*s + digits[i]) % p3
   131  		if i%2 == 0 {
   132  			s0 = (s0 + digits[i]) % 11
   133  		} else {
   134  			s1 = (s1 + digits[i]) % 11
   135  		}
   136  	}
   137  
   138  	for i := 0; i < len(h); i++ {
   139  		sh = (w*sh + int(h[i])) % p5
   140  	}
   141  
   142  	checksum = ((((n%5)*11+s0)*11+s1)*p3 + s + sh) % p5
   143  	checksum = (checksum * m) % p5
   144  
   145  	for i := 0; i < 5; i++ {
   146  		answer = string(asciiA+rune(checksum%26)) + answer
   147  		checksum /= 26
   148  	}
   149  
   150  	return answer
   151  }
   152  
   153  func (id AccountID) _IsEntityID() {}
   154  
   155  // func (id FileID) _IsEntityID()     {}
   156  // func (id ContractID) _IsEntityID() {}