github.com/geniusesgroup/libgo@v0.0.0-20220713101832-828057a9d3d4/pehrest/hash-transaction-finish.go (about)

     1  /* For license and copyright information please see LEGAL file in repository */
     2  
     3  package pehrest
     4  
     5  import (
     6  	"../authorization"
     7  	"../ganjine"
     8  	"../protocol"
     9  	"../srpc"
    10  	"../syllab"
    11  )
    12  
    13  // HashTransactionFinishService store details about HashTransactionFinish service
    14  var HashTransactionFinishService = service.Service{
    15  	URN:                "urn:giti:index.protocol:service:hash-transaction-finish",
    16  	Domain:             DomainName,
    17  	ID:                 15819904868420503209,
    18  	IssueDate:          1587282740,
    19  	ExpiryDate:         0,
    20  	ExpireInFavorOfURN: "",
    21  	ExpireInFavorOfID:  0,
    22  	Status:             protocol.Software_PreAlpha,
    23  
    24  	Authorization: authorization.Service{
    25  		CRUD:     authorization.CRUDUpdate,
    26  		UserType: protocol.UserType_App,
    27  	},
    28  
    29  	Detail: map[protocol.LanguageID]service.ServiceDetail{
    30  		protocol.LanguageEnglish: {
    31  			Name: "Index Hash - Transaction Finish",
    32  			Description: `use to approve transaction!
    33  Transaction Manager will set record and index! no further action need after this call!`,
    34  			TAGS: []string{},
    35  		},
    36  	},
    37  
    38  	SRPCHandler: HashTransactionFinishSRPC,
    39  }
    40  
    41  // HashTransactionFinish approve transaction!
    42  // Transaction Manager will set record and index! no further action need after this call!
    43  func HashTransactionFinish(req *HashTransactionFinishReq) (err protocol.Error) {
    44  	var node protocol.ApplicationNode
    45  	node, err = protocol.App.GetNodeByStorage(req.MediaTypeID, req.IndexKey)
    46  	if err != nil {
    47  		return
    48  	}
    49  
    50  	if node.Node.State == protocol.ApplicationState_LocalNode {
    51  		return HashTransactionFinish(req)
    52  	}
    53  
    54  	var st protocol.Stream
    55  	st, err = node.Conn.MakeOutcomeStream(0)
    56  	if err != nil {
    57  		return
    58  	}
    59  
    60  	st.Service = &HashTransactionFinishService
    61  	st.OutcomePayload = req.ToSyllab()
    62  
    63  	err = node.Conn.Send(st)
    64  	return
    65  }
    66  
    67  // HashTransactionFinishSRPC is sRPC handler of HashTransactionFinish service.
    68  func HashTransactionFinishSRPC(st protocol.Stream) {
    69  	if st.Connection.UserID != protocol.OS.AppManifest().AppUUID() {
    70  		// TODO::: Attack??
    71  		err = authorization.ErrUserNotAllow
    72  		return
    73  	}
    74  
    75  	var req = &HashTransactionFinishReq{}
    76  	req.FromSyllab(srpc.GetPayload(st.IncomePayload))
    77  
    78  	err = HashTransactionFinish(req)
    79  	st.OutcomePayload = make([]byte, srpc.MinLength)
    80  }
    81  
    82  // HashTransactionFinishReq is request structure of HashTransactionFinish()
    83  type HashTransactionFinishReq struct {
    84  	Type     ganjine.RequestType
    85  	IndexKey [32]byte
    86  	Record   []byte
    87  }
    88  
    89  // HashTransactionFinish approve transaction!
    90  func HashTransactionFinish(req *HashTransactionFinishReq) (err protocol.Error) {
    91  	if req.Type == ganjine.RequestTypeBroadcast {
    92  		// tell other node that this node handle request and don't send this request to other nodes!
    93  		req.Type = ganjine.RequestTypeStandalone
    94  		var reqEncoded = req.ToSyllab()
    95  
    96  		// send request to other related nodes
    97  		for i := 1; i < len(ganjine.Cluster.Replications.Zones); i++ {
    98  			var conn = ganjine.Cluster.Replications.Zones[i].Nodes[ganjine.Cluster.Node.ID].Conn
    99  			var st protocol.Stream
   100  			st, err = conn.MakeOutcomeStream(0)
   101  			if err != nil {
   102  				// TODO::: Can we easily return error if two nodes did their job and not have enough resource to send request to final node??
   103  				return
   104  			}
   105  
   106  			st.Service = &service.Service{
   107  				URN:    "urn:giti:index.protocol:service:---",
   108  				Domain: DomainName, ID: 15819904868420503209}
   109  			st.OutcomePayload = reqEncoded
   110  
   111  			err = conn.Send(st)
   112  			if err != nil {
   113  				// TODO::: Can we easily return error if two nodes do their job and just one node connection lost??
   114  				return
   115  			}
   116  
   117  			// TODO::: Can we easily return response error without handle some known situations??
   118  			err = err
   119  		}
   120  	}
   121  
   122  	// Do for i=0 as local node
   123  	err = ganjine.Cluster.TransactionManager.FinishTransaction(req.IndexKey, req.Record)
   124  	return
   125  }
   126  
   127  /*
   128  	-- Syllab Encoder & Decoder --
   129  */
   130  
   131  // FromSyllab decode from buf to req
   132  // Due to this service just use internally, It skip check buf size syllab rule! Panic occur if bad request received!
   133  func (req *HashTransactionFinishReq) FromSyllab(payload []byte, stackIndex uint32) {
   134  	req.Type = ganjine.RequestType(syllab.GetUInt8(buf, 0))
   135  	copy(req.IndexKey[:], buf[1:])
   136  	// Due to just have one field in res structure we break syllab rules and skip get address and size of res.Record from buf
   137  	req.Record = buf[33:]
   138  	return
   139  }
   140  
   141  // ToSyllab encode req to buf
   142  func (req *HashTransactionFinishReq) ToSyllab(payload []byte, stackIndex, heapIndex uint32) (freeHeapIndex uint32) {
   143  	buf = make([]byte, req.LenAsSyllab()+4) // +4 for sRPC ID instead get offset argument
   144  	syllab.SetUInt8(buf, 4, uint8(req.Type))
   145  	copy(buf[5:], req.IndexKey[:])
   146  	// Due to just have one field in res structure we break syllab rules and skip set address and size of res.Record in buf
   147  	// syllab.SetUInt32(buf, 37, res.LenOfSyllabStack())
   148  	// syllab.SetUInt32(buf, 45, uint32(len(res.Record)))
   149  	copy(buf[37:], req.Record[:])
   150  	return
   151  }
   152  
   153  func (req *HashTransactionFinishReq) LenOfSyllabStack() uint32 {
   154  	return 33
   155  }
   156  
   157  func (req *HashTransactionFinishReq) LenOfSyllabHeap() (ln uint32) {
   158  	ln = uint32(len(req.Record))
   159  	return
   160  }
   161  
   162  func (req *HashTransactionFinishReq) LenAsSyllab() uint64 {
   163  	return uint64(req.LenOfSyllabStack() + req.LenOfSyllabHeap())
   164  }