To verify the auxiliary chain, you need to prove that a certain amount of work has been done upon the latest block in that auxiliary chain. As with any form of mining, this involves computing a hash to be below a threshold.
However, it doesn't matter that the pre-image of the hash has a lot of other irrelevant data in it too, so long as it contains the relevant auxiliary-block header in there somewhere. I.e. from a proof-of-work perspective it makes no difference if you calculate this:
while(h > aux-threshold) {
h = hash(aux-header + nonce)
nonce++
}
result = nonce
versus this:
container = hash(hash(aux-header) + other-data)
while(h > aux-threshold) {
h = hash(container + nonce)
nonce++
}
result = nonce
Both will take the same amount of work and both will prove that the work has been done on aux-header
. This is so because container
can be proven to contain the aux-header, and since aux-header
and other-data
are stored in the aux-chain block and the hash can be re-computed at any time.
So, for merged mining, container
is actually the hashed header of the parent-chain block and aux-header
just needs to be included in the parent block somewhere. It really could be included anywhere so long as the parent block passes the verification process. For example, you could include the aux-chain-header-hash as an address in a multisig transaction, or as a piece of data that gets placed on the stack but never popped off in one of the transactions. Yet, the easiest place to put it is in the txin script of the coinbase transaction. This always contains arbitrary data anyway, and its location at the top of the chain means that other-data
can contain the smallest number of merkle branches.