---
# System prepended metadata

title: Digging into IPLD blocks.

---

# Digging into IPLD blocks.

### JSON Decoded
* IPLD is stored in `blocks` table
* Actual data in stored in `eth.` tables which are indexed.

#### Data for block num 2

mh_key: `/blocks/DMQGSADIA6THF5FDH42G47QWCC6LWI3ORTOBVCUU3ZS4QUV5HA65SIY`

CID: `bagiacgzaneagqb5gol2kgpzunz7bmef4xmrw5dg4dkfjjxtfzbjl2ob53erq`

JSON IPLD:
```json=
{
	"bloom": "0x00000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000002000020000000000000000000800000000000000000000000010000000000000000000001000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000004000020000000000000000000000000000000000000000800000000000000000000000000",
	"coinbase": "0x0000000000000000000000000000000000000000",
	"difficulty": 2,
	"extra": "0xd883010a02846765746888676f312e31352e35856c696e757800000000000000f599bfe3192d77e03ed67ba1d35c285c493457c7e0d54cd872b90c954dbe2f100a6306b1f1887f764393e02887c657d9a5f9d2a6f00ae3fcc155f8714005f71701",
	"gaslimit": 280925489332226,
	"gasused": 1228199,
	"mixdigest": "0x0000000000000000000000000000000000000000000000000000000000000000",
	"nonce": "0x0000000000000000",
	"number": 2,
	"parent": {
		"/": "bagiacgzaxfsywswwzpi624hr6bbgwo2q3ofwdp5jaipb7zgj27s4e3cj5t6q"
	},
	"receipts": {
		"/": "bagkacgzabc5v6foe263w342zv2pygyu7nqmlhlggbedtvsu36tafmv3nntlq"
	},
	"root": {
		"/": "baglacgzaofo7kmaojlhmg7bd6ywn24j5sj2qnzgciyofnx6wixlamwgwc6za"
	},
	"time": 1629445383,
	"tx": {
		"/": "bagjacgza2bf5epg2fn2jytr2b5fuaahox65pb5f6rvoh4aypak6okrnov7qq"
	},
	"uncles": {
		"/": "bagiqcgzadxge32g6y5oxvk4fwvt3ntgudljreri3ssfhie7qufbp2qgusndq"
	}
}
```

Parent(Block 1): `bagiacgzaxfsywswwzpi624hr6bbgwo2q3ofwdp5jaipb7zgj27s4e3cj5t6q`

#### Relation between `mh_key` and `cid`
```go=
// indexer_test.go

// MultihashKeyFromCID converts a cid into a blockstore-prefixed multihash db key string
func MultihashKeyFromCID(c cid.Cid) string {
	dbKey := dshelp.MultihashToDsKey(c.Hash())
	return blockstore.BlockPrefix.String() + dbKey.String()
}


func TestCIDtoMhKey(t *testing.T) {
	headerCID, err := cid.Parse("bagiacgzaneagqb5gol2kgpzunz7bmef4xmrw5dg4dkfjjxtfzbjl2ob53erq")
	require.NoError(t, err)

	mhKey := shared.MultihashKeyFromCID(headerCID)
	require.Equal(t, mhKey, "/blocks/DMQGSADIA6THF5FDH42G47QWCC6LWI3ORTOBVCUU3ZS4QUV5HA65SIY")
}
```

#### Relation between `data` and `cid`
```go=
// NewEthHeader converts a *types.Header into an EthHeader IPLD node
func NewEthHeader(header *types.Header) (*EthHeader, error) {
	headerRLP, err := rlp.EncodeToBytes(header)
	if err != nil {
		return nil, err
	}
	c, err := RawdataToCid(MEthHeader, headerRLP, mh.KECCAK_256)
	if err != nil {
		return nil, err
	}
	return &EthHeader{
		Header:  header,
		cid:     c,
		rawdata: headerRLP,
	}, nil
}
```
We take the RLP encoding of any struct and then covert it to CID by adding a data type to it


### Verify tx root hash in block header
```go=
func TestTxHash(t *testing.T) {
	var ethTxNodes []*EthTx
	transactionTrie := newTxTrie()

	txData, err := ioutil.ReadFile("./test_data/tx_data")
	require.NoError(t, err)

	tx := new(types.Transaction)
	tx.UnmarshalBinary(txData)

	ethTx, err := NewEthTx(tx)
	require.NoError(t, err)
	ethTxNodes = append(ethTxNodes, ethTx)

	// There is only one txn
	err = transactionTrie.add(0, ethTx.RawData())
	require.NoError(t, err)

	txRHash := common.BytesToHash(transactionTrie.rootHash())
	cid := commonHashToCid(MEthTxTrie, txRHash)
	fmt.Println(cid)

	require.Equal(t, cid.String(), "bagjacgza2bf5epg2fn2jytr2b5fuaahox65pb5f6rvoh4aypak6okrnov7qq")
}
```

```go=
func TestTxHash(t *testing.T) {
	var ethTxNodes []*EthTx
	transactionTrie := newTxTrie()

	txData, err := ioutil.ReadFile("./test_data/tx_data")
	require.NoError(t, err)

	tx := new(types.Transaction)
	tx.UnmarshalBinary(txData)

	ethTx, err := NewEthTx(tx)
	require.NoError(t, err)
	ethTxNodes = append(ethTxNodes, ethTx)

	// There is only one txn
	err = transactionTrie.add(0, ethTx.RawData())
	require.NoError(t, err)

	txRHash := common.BytesToHash(transactionTrie.rootHash())
	cid := commonHashToCid(MEthTxTrie, txRHash)

	n, err := transactionTrie.getNodes()
	require.NoError(t, err)

	fmt.Println("Length: ", len(n))

	// Same data in stored twice. One as txn trie leaf and another time as txn.
	fmt.Println("Tx encoded data:", common.Bytes2Hex(ethTx.RawData()))
	fmt.Println("Trie node:", common.Bytes2Hex(n[0].RawData()))
	fmt.Println("CID:", cid)

	require.Equal(t, cid.String(), "bagjacgza2bf5epg2fn2jytr2b5fuaahox65pb5f6rvoh4aypak6okrnov7qq")
}
```


#### Decoding a TX IPLD
```go=
func TestTxHash(t *testing.T) {
	txData, err := ioutil.ReadFile("./test_data/tx_data")
	require.NoError(t, err)

	tx := new(types.Transaction)
	tx.UnmarshalBinary(txData)

	data, err := json.MarshalIndent(tx, " ", " ")
	require.NoError(t, err)

	fmt.Println(string(data))
}
```

#### Converting log trie node to log data
```go=
func TestProcessLogs(t *testing.T) {
	logs := []*types.Log{mocks.MockLog1, mocks.MockLog2}
	nodes, cids, _, err := processLogs(logs)
	require.NoError(t, err)

	for idx, n := range nodes {
		var nodeElements []interface{}
		rlp.DecodeBytes(n.RawData(), &nodeElements)
		require.NoError(t, err)

		// This is not needed
		var log types.Log
		err = rlp.DecodeBytes(nodeElements[1].([]byte), &log)
		require.NoError(t, err)
		fmt.Println("Log: ", log)

		logRaw, err := rlp.EncodeToBytes(logs[idx])
		require.NoError(t, err)
		require.Equal(t, logRaw, nodeElements[1].([]byte))
	}

	require.GreaterOrEqual(t, len(nodes), len(logs))
	require.Equal(t, len(logs), len(cids))
}
```


### Trie keys is index 
https://ethereum.stackexchange.com/questions/35784/verifying-a-transaction-root-by-hand
**Important** https://eth.wiki/en/fundamentals/patricia-tree
https://ethereum.stackexchange.com/questions/16117/proving-the-existence-of-logs-to-the-blockchain

```
Each receipt, denoted BR[i] for the ith transaction, is placed in an index-keyed trie and the root recorded in the header as He. The transaction receipt is a tuple of four items comprising the post-transaction state, Rσ, the cumulative gas used in the block containing the transaction receipt as of immediately after the transaction has happened, Ru, the set of logs created through execution of the transaction, Rl and the Bloom filter composed from information in those logs...
```
https://blog.ethereum.org/2015/11/15/merkling-in-ethereum/