Skip to content

Instantly share code, notes, and snippets.

@emg110
Last active October 25, 2023 12:29
Show Gist options
  • Save emg110/991616476963df775327442e58ffaa16 to your computer and use it in GitHub Desktop.
Save emg110/991616476963df775327442e58ffaa16 to your computer and use it in GitHub Desktop.
This Gist contains all snippets and content regarding INNER-TXN ID ISSUE CASE

INNER-TXN ID ISSUE CASE

The construct map

CONCAT_ARRAYS(Byte array from "TX" (protocol.Transaction), Parent Tx id byte array, index of inner-txn in big endian byte array, inner-txn msgpack encoded body byte array)

Sequence of Byte Arrays in Txid Byte array from "TX" (protocol.Transaction): The function starts by getting a buffer from getTxEncodingBuf(), which already contains the protocol.Transaction bytes.this is the first part of the sequence.

Parent Tx id byte array: The function then appends the parent transaction ID (parent[:]) to the buffer. This becomes the second part of the sequence.

Index of inner-txn in big endian byte array: An 8-byte array (indexBuf) is created to store the index in big-endian format. This is then appended to the existing buffer, making it the third part of the sequence.

Inner-txn msgpack encoded body byte array: Finally, the transaction (tx) itself is msgpack encoded using tx.MarshalMsg(input) and appended to the buffer. This is the fourth and final part of the sequence.

according to the code the exact order is:

  • Byte array from "TX" (protocol.Transaction)
  • Parent Tx id byte array
  • Index of inner-txn in big endian byte array
  • Inner-txn msgpack encoded body byte array

Related Go Code

// txEncodingPool holds temporary byte slice buffers used for encoding transaction messages.
// Note, it prepends protocol.Transaction tag to the buffer economizing on subsequent append ops.
var txEncodingPool = sync.Pool{
	New: func() interface{} {
		size := txAllocSize() + len(protocol.Transaction)
		buf := make([]byte, len(protocol.Transaction), size)
		copy(buf, []byte(protocol.Transaction))
		return &txEncodingBuf{b: buf}
	},
}


// getTxEncodingBuf returns a wrapped byte slice that can be used for encoding a
// temporary message.  The byte slice length of encoded Transaction{} object.
// The caller gets full ownership of the byte slice,
// but is encouraged to return it using putEncodingBuf().
func getTxEncodingBuf() *txEncodingBuf {
	buf := txEncodingPool.Get().(*txEncodingBuf)
	return buf
}
type MicroAlgos struct {
	Raw uint64
}

func (a MicroAlgos) MarshalMsg(b []byte) (o []byte) {
	o = msgp.Require(b, msgp.Uint64Size)
	o = msgp.AppendUint64(o, a.Raw)
	return
}

// putTxEncodingBuf places a byte slice into the pool of temporary buffers
// for encoding.  The caller gives up ownership of the byte slice when
// passing it to putTxEncodingBuf().
func putTxEncodingBuf(buf *txEncodingBuf) {
	buf.b = buf.b[:len(protocol.Transaction)]
	txEncodingPool.Put(buf)
}
// The main function in subject
func (tx Transaction) InnerID(parent Txid, index int) Txid {

// inner-txn body bytes
	buf := getTxEncodingBuf()
	// append parent TXN ID
	input := append(buf.b, parent[:]...)
	var indexBuf [8]byte
	binary.BigEndian.PutUint64(indexBuf[:], uint64(index))
	// Append index
	input = append(input, indexBuf[:]...)
	enc := tx.MarshalMsg(input)
	if cap(enc) > cap(buf.b) {
		buf.b = enc
	}
	defer putTxEncodingBuf(buf)
	return Txid(crypto.Hash(enc))
}
![image](https://user-images.githubusercontent.com/1900448/277962749-f332dd50-8ed5-4684-955c-e7bb8a62c5cb.png)

The JSSDK code

const ALGORAND_TRANSACTION_LENGTH = 52;
tag = Buffer.from('TX');

rawTxID() {
    const enMsg = this.toByte();
    const gh = Buffer.from(utils.concatArrays(this.tag, enMsg));
    return Buffer.from(nacl.genericHash(gh));
  }
txID() {
    const hash = this.rawTxID();
    return base32.encode(hash).slice(0, ALGORAND_TRANSACTION_LENGTH);
  }

export function genericHash(arr: sha512.Message) {
  return sha512.sha512_256.array(arr);
}

toByte() {
    return encoding.encode(this.get_obj_for_encoding());
  }![image](https://user-images.githubusercontent.com/1900448/277963542-f9fb2f6c-6d97-4779-87fb-ed295eaa0b84.png)

Links:

msgpack Message Marshaling

encoding

SDK related section

go-algorand exact funciton for generating inner TXN ID

the solution structure so far

Methods in deployer Class

  • testRegenerateTransaction : Main method containing majority of the code for easier tracking and debug
  • printTransactionLogsFromBlocks
  • printTransactionLogsFromBlocks (gets the txn, inner TXN and logs from /block endpoint of Algod)
  • printTransactionLogsFromIndexer (gets and prints logs from indexer , just for logging and not used in process)

How to run:

  • branch the gora-desense-smartcontracts repo
  • pull your created branch
  • npm install
  • npm start

Please use LTS version of nodeJS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment