github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/node.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  	"bytes"
    25  	"crypto/sha512"
    26  	"crypto/tls"
    27  	"crypto/x509"
    28  	"encoding/hex"
    29  	"encoding/pem"
    30  	"sync"
    31  	"time"
    32  
    33  	"google.golang.org/grpc"
    34  	"google.golang.org/grpc/codes"
    35  	"google.golang.org/grpc/credentials"
    36  	"google.golang.org/grpc/keepalive"
    37  	"google.golang.org/grpc/status"
    38  )
    39  
    40  // _Node represents a node on the network
    41  type _Node struct {
    42  	*_ManagedNode
    43  	accountID         AccountID
    44  	channel           *_Channel
    45  	addressBook       *NodeAddress
    46  	verifyCertificate bool
    47  	channelMutex      sync.Mutex
    48  }
    49  
    50  func _NewNode(accountID AccountID, address string, minBackoff time.Duration) (node *_Node, err error) {
    51  	node = &_Node{
    52  		accountID:         accountID,
    53  		verifyCertificate: true,
    54  	}
    55  	node._ManagedNode, err = _NewManagedNode(address, minBackoff)
    56  	return node, err
    57  }
    58  
    59  func (node *_Node) _GetKey() string {
    60  	return node.accountID.String()
    61  }
    62  
    63  func (node *_Node) _SetMinBackoff(waitTime time.Duration) {
    64  	node._ManagedNode._SetMinBackoff(waitTime)
    65  }
    66  
    67  func (node *_Node) _GetMinBackoff() time.Duration {
    68  	return node._ManagedNode._GetMinBackoff()
    69  }
    70  
    71  func (node *_Node) _SetMaxBackoff(waitTime time.Duration) {
    72  	node._ManagedNode._SetMaxBackoff(waitTime)
    73  }
    74  
    75  func (node *_Node) _GetMaxBackoff() time.Duration {
    76  	return node._ManagedNode._GetMaxBackoff()
    77  }
    78  
    79  func (node *_Node) _InUse() {
    80  	node._ManagedNode._InUse()
    81  }
    82  
    83  func (node *_Node) _IsHealthy() bool {
    84  	return node._ManagedNode._IsHealthy()
    85  }
    86  
    87  func (node *_Node) _IncreaseBackoff() {
    88  	node._ManagedNode._IncreaseBackoff()
    89  }
    90  
    91  func (node *_Node) _DecreaseBackoff() {
    92  	node._ManagedNode._DecreaseBackoff()
    93  }
    94  
    95  func (node *_Node) _Wait() time.Duration {
    96  	return node._ManagedNode._Wait()
    97  }
    98  
    99  func (node *_Node) _GetUseCount() int64 {
   100  	return node._ManagedNode._GetUseCount()
   101  }
   102  
   103  func (node *_Node) _GetLastUsed() time.Time {
   104  	return node._ManagedNode._GetLastUsed()
   105  }
   106  
   107  func (node *_Node) _GetManagedNode() *_ManagedNode {
   108  	return node._ManagedNode
   109  }
   110  
   111  func (node *_Node) _GetAttempts() int64 {
   112  	return node._ManagedNode._GetAttempts()
   113  }
   114  
   115  func (node *_Node) _GetAddress() string {
   116  	return node._ManagedNode._GetAddress()
   117  }
   118  
   119  func (node *_Node) _GetReadmitTime() *time.Time {
   120  	return node._ManagedNode._GetReadmitTime()
   121  }
   122  
   123  func (node *_Node) _GetChannel(logger Logger) (*_Channel, error) {
   124  	node.channelMutex.Lock()
   125  	defer node.channelMutex.Unlock()
   126  
   127  	if node.channel != nil {
   128  		return node.channel, nil
   129  	}
   130  
   131  	var kacp = keepalive.ClientParameters{
   132  		Time:                10 * time.Second,
   133  		Timeout:             2 * time.Second,
   134  		PermitWithoutStream: true,
   135  	}
   136  
   137  	var conn *grpc.ClientConn
   138  	var err error
   139  	security := grpc.WithInsecure() //nolint
   140  	if !node.verifyCertificate {
   141  		println("skipping certificate check")
   142  	}
   143  	if node._ManagedNode.address._IsTransportSecurity() {
   144  		security = grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{
   145  			InsecureSkipVerify: true, // nolint
   146  			VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
   147  				if node.addressBook == nil {
   148  					logger.Warn("skipping certificate check since no cert hash was found")
   149  					return nil
   150  				}
   151  
   152  				if !node.verifyCertificate {
   153  					return nil
   154  				}
   155  
   156  				for _, cert := range rawCerts {
   157  					var certHash []byte
   158  
   159  					block := &pem.Block{
   160  						Type:  "CERTIFICATE",
   161  						Bytes: cert,
   162  					}
   163  
   164  					var encodedBuf bytes.Buffer
   165  					_ = pem.Encode(&encodedBuf, block)
   166  					digest := sha512.New384()
   167  
   168  					if _, err = digest.Write(encodedBuf.Bytes()); err != nil {
   169  						return err
   170  					}
   171  
   172  					certHash = digest.Sum(nil)
   173  
   174  					if string(node.addressBook.CertHash) == hex.EncodeToString(certHash) {
   175  						return nil
   176  					}
   177  				}
   178  
   179  				return x509.CertificateInvalidError{
   180  					Cert:   nil,
   181  					Reason: x509.Expired,
   182  					Detail: "",
   183  				}
   184  			},
   185  		}))
   186  	}
   187  
   188  	conn, err = grpc.NewClient(node._ManagedNode.address._String(), security, grpc.WithKeepaliveParams(kacp))
   189  	if err != nil {
   190  		return nil, status.Error(codes.ResourceExhausted, "dial timeout of 10sec exceeded")
   191  	}
   192  
   193  	ch := _NewChannel(conn)
   194  	node.channel = &ch
   195  
   196  	return node.channel, nil
   197  }
   198  
   199  func (node *_Node) _Close() error {
   200  	node.channelMutex.Lock()
   201  	defer node.channelMutex.Unlock()
   202  
   203  	if node.channel != nil {
   204  		err := node.channel.client.Close()
   205  		node.channel = nil
   206  		return err
   207  	}
   208  
   209  	return nil
   210  }
   211  
   212  func (node *_Node) _ToSecure() _IManagedNode {
   213  	managed := _ManagedNode{
   214  		address:            node.address._ToSecure(),
   215  		currentBackoff:     node.currentBackoff,
   216  		lastUsed:           node.lastUsed,
   217  		readmitTime:        node.readmitTime,
   218  		useCount:           node.useCount,
   219  		minBackoff:         node.minBackoff,
   220  		badGrpcStatusCount: node.badGrpcStatusCount,
   221  	}
   222  
   223  	return &_Node{
   224  		_ManagedNode:      &managed,
   225  		accountID:         node.accountID,
   226  		channel:           node.channel,
   227  		addressBook:       node.addressBook,
   228  		verifyCertificate: node.verifyCertificate,
   229  	}
   230  }
   231  
   232  func (node *_Node) _ToInsecure() _IManagedNode {
   233  	managed := _ManagedNode{
   234  		address:            node.address._ToInsecure(),
   235  		currentBackoff:     node.currentBackoff,
   236  		lastUsed:           node.lastUsed,
   237  		readmitTime:        node.readmitTime,
   238  		useCount:           node.useCount,
   239  		minBackoff:         node.minBackoff,
   240  		badGrpcStatusCount: node.badGrpcStatusCount,
   241  	}
   242  
   243  	return &_Node{
   244  		_ManagedNode:      &managed,
   245  		accountID:         node.accountID,
   246  		channel:           node.channel,
   247  		addressBook:       node.addressBook,
   248  		verifyCertificate: node.verifyCertificate,
   249  	}
   250  }
   251  
   252  func (node *_Node) _SetVerifyCertificate(verify bool) {
   253  	node.verifyCertificate = verify
   254  }
   255  
   256  func (node *_Node) _GetVerifyCertificate() bool {
   257  	return node.verifyCertificate
   258  }