I suggest that we use a remark field (perhaps remark9) to indicate a due time (in block) for a transaction. If time/block is passed, transaction is rejected and removed from mempool. If more complex situations are needed, we can add some extra verification code here too.
https://github.com/neo-project/neo/blob/master/neo/Core/TransactionAttributeUsage.cs#L25
Why not use TransactionAttribute?
That's a good idea Erik, you mean, we can create a field just for it right? I thought all numbers were taken, but now I see we still have space there! :) Much better... no Remark, we create another one, 0xc0 perhaps? There's space after Hash15 0xaf and before Remark 0xf0.
No. I mean why not use the TransactionAttributeUsage.Script?
You mean, to put this logic inside the Verification contract? I see this TransactionAttributeUsage.Script having extra 20bytes, and it seems to be used here: https://github.com/neo-project/neo/blob/35ff9a68010bdddc160840f222df13c3c46290f6/neo/Core/Transaction.cs#L231
We need some extra information to be able to drop transactions even on relay nodes... for example, I submit an asset transfer tx now at block X, from a standard account, and add an extra "flag" indicating that this tx will be invalid after block Y. If we use .Script attribute, we have 20 bytes to describe this situation, and wouldn't this flag already be used to carry the ScriptHash of the source contract?
I agree that it would be nice to put a general code there, so we could control more than a simple "block time" verification... but I guess that will also become more complex. Probably I'm misunderstanding something here :)
TransactionAttributeUsage.Script is just a script hash. The real script is in the Witness.
Complex... :dagger:
Is it related to change the current size https://github.com/neo-project/neo/blob/35ff9a68010bdddc160840f222df13c3c46290f6/neo/Core/TransactionAttribute.cs#L31
from 20 to something else and append the information to it? https://github.com/neo-project/neo/blob/35ff9a68010bdddc160840f222df13c3c46290f6/neo/Core/Transaction.cs#L231
This Erik is like a chess player, likes to break our minds... hahaha We need a biginteger representing a block limit, and Script 0x20 carries a 20 byte data that is a ScriptHash. In this code, p.Data is converted directly to UInt160, but I don't know who sets this field (and even if it's ever used). If it's not used anymore, we can reuse it for block limit, but I'm sure he's proposing something more elaborate hahah Perhaps we create a Script validating current block, add it as another Verification script, and add its scripthash as TransactionAttributeUsage.Script? :)
Sorry for the missing document. But I have given you enough clues.
Here is the last tip:
Read these two pieces of code carefully and carefully, and you will understand that the features you want to implement already exist.
Ok Erik, I think I finally got your point. Verification Scripts must match exactly the hash list which is ordered by scripthash, including the Script Attribute 0x20. Empty Verifications are treated like external APPCALLs. So, it's simple in fact, we just submit another script attached to the transaction, which validates block height. :tada: :tada: :tada:
I guess the document would help, but I'm a bigger fan of understanding by reading the code. My goal is to fully understand 100% of NEO code, and perhaps in a few weeks more, that will be accomplished.
Since we don't use C# very often, we are building a javascript tool in NeoResearch repo called eco-sdk, with transaction build features and stuff we don't have in neon-js. It's nearly done, and using this tool I will be able to test this on javascript, share this knowledge with Neon Wallet team and put in online on neocompiler.io for everyone to learn how to use attributes. Sorry for taking your time... Thanks a lot Erik. ;)
Go for it, broda. In fact, I am learning a lot with all these code lessons, thanks, C# promotes several compact things, I am getting used to it. When we meet personally you teach me, @igormcoelho :dagger: eahuehauehaue
The parameter should be easy to adjust, Igor, maybe as a Plugin, what do you think? Because if the time per block changes we could simply change that constraint there.
Don't worry Vitor, no need to change anything, it works out of the box ;) Let's write about it for the community, just made it work!
@localhuman @Ejhfast @canesin @shargon I believe it's a good idea to add this feature in Neon Wallet, to guarantee that transactions won't be stuck forever in relay nodes, and will certainly "expire" after a given block is achieved.
@snowypowers if you want, we can easily add this to neon-js.
The mechanism is quite simple, I added the following attribute: 20f1a2db201efc86c29d1dee4f6495b783680b09dc, which is 0x20 code plus scripthash (big-endian I guess) f1a2db201efc86c29d1dee4f6495b783680b09dc. I created another witness with no invocation script (size 00) and the following verification script: 68184e656f2e426c6f636b636861696e2e47657448656967687402a00f9f. The scripthash matches the one presented up on attribute, and the meaning of this script is:
68 SYSCALL 184e656f2e426c6f636b636861696e2e476574486569676874 # Neo.Blockchain.GetHeight
02 PUSHBYTES2 a00f # 4000
9f LT # Returns 1 if a is less than b, 0 otherwise.
In other words, this transaction is only valid if block height is below 4000. I think neon wallet should allow a limit on blocks ahead, such as 5 or 10... or even allow some configuration of this value in parameter section, if network is overloaded. Anyway, any value is good enough to make sure it will expire at some moment :)
Just to register, this was the successful transaction (using neocompiler.io w1 address):
Most helpful comment
Sorry for the missing document. But I have given you enough clues.
Here is the last tip:
https://github.com/neo-project/neo/blob/aaa1282cd16b2b2b4f2b8989066606d43b1873bd/neo/Core/Transaction.cs#L227-L242
https://github.com/neo-project/neo/blob/aaa1282cd16b2b2b4f2b8989066606d43b1873bd/neo/Core/Helper.cs#L46-L83
Read these two pieces of code carefully and carefully, and you will understand that the features you want to implement already exist.