Since any new on-chain programming language in Bitcoin will have to be supported forever there will always be the objection that whatever is proposed doesn’t do enough and will just be legacy baggage after something better is deployed later. The obvious fix is to make an environment which can do everything but that runs headlong into ‘everything’ being scary. In Chia we’ve gone full steam ahead with the Bitcoin Script research program so I can tell you what ‘everything’ is and what the objections to parts of it are. Some of these may sound inane to you, but trust me these have all been major sources of angst in the past. If people are able to come to agreement about some or all of them now then great. I’m posting this to at least help have a conversation about it. The counterarguments for pieces of functionality given below are taken from Bitcoin lore which may not be well documented or even well remembered any more as there’s been turnover among core developers, but these are all objections given by important core developers in years past.
Turing complete language/Covenants/Capabilities
These three are lumped together because in general if a turing complete language is allowed that naturally produces covenants and capabilities as a side effect. In the past Bitcoin developers were skeptical of covenants in general but seem to have mostly gotten over it now. The difference has to do with whether a covenant is attached as a rider or something which the recipient has to fully opt in to. There’s nothing inherently wrong with funds being restricted. The sender of funds can always do an equivalent thing by simply not sending the funds. The problem is if a recipient thinks that they’ve gotten funds but those funds are actually encumbered by rules they don’t realize are there. Since all serious proposals for covenants in Bitcoin involve them being enforced by scriptpubkeys this is taken care of.
Capabilities haven’t been discussed as much but the Chialisp trick for implementing them once you have a turing complete language seems to be a no brainer. All that’s necessary is for a scriptpubkey to have some way of knowing what UTXO it’s a part of and to have sandboxing possible in the language.
Deduplicating code
As soon as you allow a turing complete language on chain you run headlong into having programs which are so long that they’re cost prohibitive to deploy. The only practical way around this is to allow code to be reused. There are two approaches to this: either allow code reuse within a block, or allow references to code which was explicitly made available from older blocks. The problem with the first one of these is that it makes the costs of including transactions in blocks multidimensional with there being group discounts. The problem with the second one is that it can cause a transaction to go from valid to invalid if it depended on the previous block and that gets reorged out. Neither of these is perfect, but both are workable and at least one of them has to be done to have any hope of widespread complex programs without a zillion little forks adding each of them.
Access to time
In Bitcoin currently timelocks are restricted to being able to make requirements that particular sends only happen after a particular time. The theory is that transaction validity should be strictly monotonic: A transaction can go from invalid to valid because enough time passed, but not from valid to invalid. That way things which are in the mempool only get kicked out when they succeed or the fee rate gets above them.
Obviously there’s a big exception to mempool monotinicity: Transactions can already get kicked out because one of their inputs got spent. That is a very narrow and well defined property but then the current time is also a very narrow and well defined property. Handling the mempool edge cases is some work but not a super compelling argument against the functionality.
The most basic use of time functionality is to keep transactions from ever getting into a limbo ‘failed’ state. If a transaction doesn’t go through for too long you probably want to give up on it, but then it’s in the limbo state of not knowing whether it will get through eventually. You can force it to fail but spending one of its inputs, but if fees were too high for the original transaction to go through then fees may be too high for the cancellation transaction to go through and you’re just stuck. Allowing transactions to simply say that they can’t be spent past a certain time would fix this elegantly.
A strong argument for a supported not valid after is that you can implement a very bad one. For example you can have UTXOs which are anyone can spend but can’t be spent until a set time, and you make a transaction which has to include one of those on the assumption that someone will spend them as soon as it becomes possible. This is extremely janky but it’s the sort of thing which people are likely to do if a supported not valid after is not available.
One argument against allowing not valid after is that it may allow transactions to game their priority by expiring soon. Thankfully due to real decentralization a miner making one block has no idea whether it’s them or some unrelated miner making the next block and it’s usually someone unrelated. The incentives work out that it’s best for miners to let in whatever makes them the most in transaction fees, so there doesn’t seem to be a real issue here.
A related problem with not valid after is that it can allow someone making a transaction to incentivize a miner to set the time of the current block earlier than is accurate by making a high fee transaction which is dependent on an earlier time. In Chia this is avoided by making the relevant time be the one from the previous transaction block, which mostly fixes the problem because of the same real decentralization as the previous issue. There’s a separate mechanism for a coin to assert that it’s spent in the same block as it’s created because that relies on a concept of ‘now’ for a time which technically hasn’t been set yet. This approach works fine but the subtle details need to be hashed out carefully.
Assert UTXO spent
It would be good to have a better answer to how to add fees to a transaction after it’s done being created would be a good idea. One approach would be to allow one transaction to depend on another one without the second one opting in. This violates the principle that transactions shouldn’t be able to influence transactions outside of themselves, but since it can only do so in a positive direction it doesn’t allow censorship and it allows for simple solutions to things which are otherwise huge headaches. Reducing the level of dependence to only allow one transaction to require a certain UTXO be spent instead of specifying the full details of the other transaction would be even less deviation from the principle.
I think you have just described Ethereum. I am pretty sure that is how Ethereum started: a thought exercise, “What if we made the Bitcoin scripting language Turing complete?”, and all the pitfalls and complications of doing so. Making sure no infinite loops would lock it up forever, while at the same time allowing increasingly complex programs without having to take the easy way out by simply hard coding a CPU cycle limit. What inputs and outputs the programs would have, including self reflection so they can access the blockchain and store their own persistent data. Security around all of this. I wish I had bought some Ethereum when it first came out and the price was less than $100 then.
To be honest, I'm waiting for nft 2.0. Personally, I think that's the future. I'm tired of the many Spotify, Netflix and Apple TV services. It seems to me that all this needs to be thought out, implemented and simplified.This will be convenient and appropriate for large organizations. Reducing staff, salaries, taxes, accounting, etc. nft is at the beginning of its journey, but I see potential in it.Chia is perfect for this😊