Use Tendermint transaction tagging
Tendermint has support for tagging transactions, which lets us do two things: index them so we can look up all past transactions for a given tag, or filter incoming transactions so e.g. light clients can receive only the transactions they care about.
It would be nice to have a way to tag and filter transactions from Lotion, and possibly a default tagging behavior so developers don't have to think about this (e.g. tag by each mutated key in the state, so counter transactions would be tagged with root.count because they mutated count).
@mappum It is interesting. I have checked this out https://tendermint.com/docs/app-dev/indexing-transactions.html#adding-tags for adding tags in deliverTx method. And I tried adding tags in deliverTx response in abci-server.ts. But it is not working.
My step is:
- modify config.toml to set
index_all_tags = truebefore tendermint process start - modify abci-server.ts https://github.com/keppel/lotion/blob/develop/src/abci-server.ts#L21
to like this
return { code: 0, data: 'test123', tags: [{ "key1": 'value1' }] }; - make a rpc broadcast_tx_commit request to tendermint
- lookup the tx record (e.g. /tx?hash=0x0276C145AED6B9F89551B348D5E9CD678205CE3B) The response:
{
"jsonrpc": "2.0",
"id": "",
"result": {
"hash": "0276C145AED6B9F89551B348D5E9CD678205CE3B",
"height": "5",
"index": 0,
"tx_result": {
"data": "test120=",
"tags": [
{}
]
},
"tx": "AAAAC3siY291bnQiOjF9AAAfcg=="
}
}
You can see the empty object in result.tx_result.tags' array
Do you have an idea for this? Thanks.
I seem to have debugged half of the issue. The Tendermint node was rejecting the tag as was shown in the debug output with logTendermint set to true:
I[11-01|00:38:10.491] Got tag with an empty key (skipping)
I replaced:
{ code: 0, data: 'test123', tags: [{ "key1": 'value1' }] }
with
{ code: 0, data: 'test123', tags: [{ key: "key1", value: 'value1' }] }
The Tendermint node now accepts the tag, or at least it seems to because the error message goes away.
Still can't query with tx_search however..
@fumecow Thank you for your finding
Please take a look at this https://github.com/tendermint/tendermint/issues/2051 You can see the value of "key" and "value" are encoded
so just replace
{ code: 0, data: 'test123', tags: [{ key: "key1", value: 'value1' }] }
with
{ code: 0, data: 'test123', tags: [{ key: Buffer.from("key1"), value: Buffer.from('value1') }] }
Try tx_search /tx_search?query="key1='value'"
Now it works!!
@kin021360 wow - thanks for finding that - working here now too!
@kin021360 May I ask you how to make a rpc broadcast_tx_commit request to tendermint?
I found types.Tx is []byte format from tendermint source code as below. But, I am not too sure if there is any method in this lotion library that creates the appropriate types.Tx format.
tendermint/rpc/core/mempool.go
func BroadcastTxCommit(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) {
...............
}
@jaybkim1
https://godoc.org/github.com/tendermint/tendermint/rpc/core#BroadcastTxCommit
https://github.com/keppel/lotion#global-chain-identifiers-and-light-clients The lotion-connect module includes the send method which is doing broadcast_tx_commit. You can try it
@kin021360 Thank you for your quick response. The docs and links are really helpful.
I tried it like below and I successfully sent a simple transaction, but now I am wondering how to make a real transaction that involves with check_tx {} and deliver_tx {}. For example, transferring coins from one account to another, requesting coins from faucet and etc.
async function send() {
let result = await connect(GCI)
console.log(await result.send({
nonce: 0
}));
}
send();
The result is as below
{
check_tx: {},
deliver_tx: {},
hash: '1659C754DF170FAE971AE06B15B14246F0B5CD12',
height: '10'
}
I took a look at the codes inside the send-tx.js file that is in the lotion-connect module.
Do you know where that tx come from ?
And, I feel like nonce cannot be generated randomly. It needs to be +1 from previous transaction's nonce. Isn't it? Also the name should be sequence or sequenceNum since that is the right name that tendermint uses.
<index.js>
let lc = await startLightClientFromGenesis(genesis, nodeAddress)
let getState = GetState(lc)
let sendTx = SendTx(lc) // I see this line will trigger to send transaction
await delay()
resolve({
getState,
send: sendTx,
state: Proxmise(async path => {
return await getState(path.join('.'))
})
})
<send-tx.js>
function SendTx(lc) {
return async function(tx) { // Where does this 'tx' inside the function come from?
let nonce = Math.floor(Math.random() * (2 << 12)) // Isn't this nonce supposed to be getting from the blockchain?
let txBytes = '0x' + encode(tx, nonce).toString('hex')
return axios
.get(parseHttpUri(lc.rpc.uri) + '/broadcast_tx_commit', {
params: { tx: txBytes }
})
.then(res => res.data.result)
}
}
I open an issue #159 regarding the height and the nonce parameters in lotion-connect module