The issue with double spending isn't that network nodes can't independently deal with it. The real problem is there's no universal way to keep consensus that can't be manipulated. Like, if the rule is to consider the transaction with the lowest TXID as valid in a double spend scenario, an attacker could just push out the transaction with the highest TXID first, and later drop the one with the lowest TXID to replace it. Essentially, a consensus protocol lets one randomly chosen node make the final call for everyone else. That's basically what miners and validators do when they create new blocks in blockchains.
Cosign Consensus comes in as an alternative that aims to handle double spending without using blockchain or either POW or POS. In this setup, transactions get individually confirmed as users pick each other randomly to cosign their inputs.
When someone initiates a new transaction, they have to gather a list of a hundred randomly chosen and shuffled payment addresses using a verifiable random function (VRF). Each address can only appear once on the list. They’re selected first from outputs in the mempool and then from UTXOs in the ledger. After the user sends out their transaction, the payment addresses in its outputs are put in the mempool so other users can pick them. When any of these outputs gets spent, anyone from the list can sign the corresponding inputs and throw in an extra output for their fee, which goes to the address that’s highest on the list.
Just run Signet: https://en.bitcoin.it/wiki/Signet
Only those, which are signed by signet miners.
You can do that in today's Script: just add OP_CHECKSIG, without any key, and then, a valid public key and signature will be required. Also, you can do "OP_CHECKSIG OP_CODESEPARATOR", if you want to sign exactly the same data as before, and remove this additional Script from the signed data.
If there are no fees, then what is the incentive to sign anything? If people have no reason to sign anyone's coins, then they can just stop doing that, and halt your network in this way.
Proof of Work is not going to disappear anytime soon. Quite the opposite: it is possible to require Proof of Work inside Script, by checking the size of the DER signature. And it can be splitted or merged with other sidechains: https://mempool.space/testnet4/tx/8397c2323e3fa099c15be68399346b2b3d223ef8e81e553242763e1a4c60771a
Also, you probably received that link at least once, but I will share it again: https://www.truthcoin.info/blog/pow-cheapest/
If you switch from Proof of Work into something else, then you will get just "hidden Proof of Work" instead, but you won't avoid it. For example: if coins are signed, then the size of the signature can act as a Proof of Work. And you will need to check things like that, for example to avoid flooding your network with a lot of fake transactions, signed by large group of signers, who can effortlessly flood your network, if there are no protections.
At the end of the day, no matter who will be selected, someone will be picked, as a cosigner. And then, that person can just sign fake transactions, or just reject to sign anything, and halt your network entirely, by making you unable to send any transaction at all.
Also, when your network will just start, then there will be just a few people interested in your system. And then, if you have for example 5 users, then it doesn't really matter, which one will be randomly picked.
Another thing is that you didn't understand, why Proof of Work is needed: you can run regtest, where every second hash is a valid block. Mining is ridiculously easy, almost nonexisting there. And if your idea would be good enough, then you could just run regtest publicly. So, why you wouldn't do that? Because making signatures is cheap. And where making a chain of signatures (even without any blocks) is cheap, then not only it can be easily produced, but also easily attacked.
So, by fighting with Proof of Work, and trying to remove it, you just open your network for "multiple history attack", where one group of nodes will sign one group of transactions, and another group of nodes will sign something completely different, and because of no mining, nobody would be able to tell, which history is the correct one.
Which could be never. When your network is small, then it can happen quite easily: if you have for example 5 nodes, then just 4 of them can decide: let's stop signing and see, what will happen. In case of Proof of Work, the network will still be pushed forward, because the remaining node can still keep mining new blocks. But in your network it is not the case, just because you removed Proof of Work entirely.
Edit: By the way, any Signet is based on assumption, that the creator is always active. And your network seems to also share that kind of assumption, because if you pick someone randomly as a cosigner, then that choice cannot be changed (because it would compromise the randomness, if it could be ignored, and the random number generator could be otherwise endlessly called, to always pick a particular cosigner; by literally using Proof of Work, by the way). Which means, that if your system would be deployed on top of Bitcoin, then the chain would be basically dead, just because Satoshi is no longer there.
And then, the question is: how your network is blocked from being halted by cosigners going offline? Another question is, how your coins could have any non-zero value, if they are produced out of thin air, without any blocks, blockchain, and any Proof of Work?
Are people sending just zero coins, and just making signatures? Because you didn't explain, how "there is no inflation". I don't know, how initial coins are distributed in your system, and if you are trying to make a new Ripple, where the creator has 100% premine, and everyone can just buy his coins.
You have to cosign something before you can spend your coins.
Fake transactions are invalid, and nodes won't even propagate invalid transactions.
Option 1 is to sign nothing. When this happens, a sender can republish their transaction with a different address for the same UTXO. When that transaction is cosigned, the unsigned transaction is discarded.
There's at least one user per address, but there can be many addresses per user, so we can never know how many users there are. Only that the number of users is equal to or less than the number of addresses. In any case, it is highly unlikely for a new coin on an exchange to have such a small number of addresses for more than a fraction of a second.
There's no inflation because coins are not generated, so the coinbase is necessarily premined.
I think it's an interesting idea. I like your insight about validation through cosigning.
I have some questions. Forgive me if they have already been answered.
1. How do you prove that the cosigners were chosen randomly?
2. How do you ensure that cosigners are available for each transaction and transactions are available to be cosigned? It seems like there is a balance that must be maintained. For example, a typical transaction has one input and two outputs. This implies a shortage of inputs available to cosign.
3. An attack seems possible in which the attacker creates transactions but refuses to cosign their assigned inputs. I think this was already suggested, but your reply was not clear to me.
By using a verifiable random function.
It's only typical for consumers to create transactions that split coins. Merchants typically create transactions that merge coins. Sometimes the number of inputs will be less than the number of outputs, which will delay cosigners, and sometimes the number of inputs will be greater than the number of outputs, which will delay confirmations, but there will always be a natural average of 1:1.
When a cosigner is nonresponsive, the sender must replace their address. They must redact the first or previous transaction before publishing a new one to avoid having more than one version of a transaction in the mempool at a time.
And who can start that kind of chain of signatures? Are there all coins assigned to the creator, or do you start from a completely empty chain? If all coins are held by the creator, then how it is better than Ripple? And if there are no coins, then who signs the first one?
How to check, if a given transaction is fake or not? If there is "no blockchain", then there is "no persistent history of any kind". You can have one transaction, sending coins from Alice to Bob, and another transaction, sending them from Alice to Charlie. How do you know, which transaction is real, and which is fake, if both signatures are correct from ECDSA point of view? And if one group of cosigners can tell you one thing, and another group of cosigners can tell you the opposite thing, how do you know, who can be trusted? Remember: you rejected Proof of Work, so all signatures on all sides are equally good, which means, that nodes can be easily fooled.
Do you mean "signing a zero hash", "signing a one hash", or "not including any signature at all"? If you don't include any signature, then it is unknown, if someone decided to not sign anything, or if you simply missed that P2P message (and then, the system is not resistant to dropped messages). If you sign zero hash, then any coin can be moved anywhere. If you sign one hash (or anything constant), then it is not resistant to SIGHASH_SINGLE bug. So, how exactly "nothing" is signed? You take SHA-256 of an empty string?
There are many dead altcoins. If you don't have any brilliant idea, then your altcoin will follow the typical path of pump and dump, where early adopters first get everything they can, then your coin will be listed on any exchange, and reach its ATH, and then it will dump to the bottom, when everyone will sell it for BTC.
In case of Proof of Work, there are limits, for example one block per 10 minutes. If you have just signatures, without any Proof of Work, then there are no rate limits. Which means, that nodes can be endlessly flooded, by a lot of people, sending everything between themselves. And because there are no fees in your system, the cost of spamming the chain is literally zero.
In that case, why it is better than Ripple? And if it isn't, then why don't you just use Ripple instead?
Which one exactly?
I don't think it is the case. You can look at some statistics from Bitcoin or other chains, and see, that many times, you have multiple inputs and outputs. And of course, if your system will for example only allow a single input and output, and would form some kind of account-based system, then just multiple transactions would be used to achieve the same thing.
What if all of them are nonresponsive? And who decides, if someone was nonresponsive, or if it was an arbitrary decision of a given coin owner? If anyone can affect the randomness, just by changing the address, then people can do that endlessly, until they will get the cosigners they want, and your randomness could be easily bypassed by anyone in that case, and replaced by "address mining", just to pick the non-random cosigners.
Of course, as always, I encourage you to try your ideas, to write some code, to make some test version, and to test everything in practice. But as you can see, if you throw away some element, for example Proof of Work, then there are many consequences of doing just that, and I don't know, if you are aware of them.
Also, every system should have its constraints, and assumptions. For example: Proof of Work assumes, that the mining majority is in honest hands. In case of 51% attacks, the system works much worse than described in the whitepaper. So, what are your constraints? Having 51% of all cosigners?
Consider a scenario where an attacker splits their coins into an incredibly large number of outputs, with small amounts in each. By submitting all of these unconfirmed outputs to the pool at once, they are able to artificially increase their chances of being selected as a cosigner, no? The PORA isn't necessarily effective if attackers can directly manipulate the odds anyway, and, as has been mentioned, since there are no fees, the cost of doing this is effectively zero.
Without a Proof of Work or some kind of mitigation mechanism, your network would constantly be susceptible to 51% attacks, at least to my understanding.
Even that part is unnecessary. In Bitcoin, we have UTXOs, which can hold zero satoshis. So, if that kind of system would just count any UTXOs, and would be deployed on top of Bitcoin, then people could artificially create a lot of outputs with zero satoshis, just to increase their chances of being selected.
But, there are bigger problems than just that: if everything is based only on signatures, and all coins are initially in the hands of the creator, then the chain of signatures can be always overwritten by the creator: in all Proof-of-Stake-like protocols, if you have 51% of coins, then you can rule the network forever.
In case of Proof of Work, having 51% here and now, means that you can only rule the network here and now. And that you have to keep spending your resources, as long as you want to keep the majority. But once someone is beaten by another miner, someone having 51% hashrate can lose its leading position. But in signature-based protocols, like Proof of Stake, signatures can be made without much effort, which means "once 51%, forever 51%" instead.
And in that case, if the network is going to be centralized anyway, and controlled by whoever will hold the premine, then why don't start with just Signet, and explicitly use something, which is based on Proof of Authority anyway?
Meaning consensus here will be made by local agreements between cosigners. Since the sender will have to Cosign along side some randomly selected cosigners and it is stated there are no fees, no block rewards no inflation, how do this cosigners get incentivized because it is obvious this will be a non-monetary participation?.
Won't they be fear of delayed transactions? Won't we have increased mempool clutter if not properly managed? How about risks of possible blackouts?.
But my thoughts implementing automatic removal and replacement of cosigners might be a better approach, If possible flag non-responsive cosigners using a reputable system.
My main problem with that approach is that it is impossible to have something like a "global mempool" you could apply a random function to select a "cosigner". Every node typically only knows a subset of the existing mempool transactions. In addition, you can create as many transactions as you like, from as many addresses as you like, even from different nodes.
So the attacker could create lots of (theoretically valid) transactions and "grind" through several different "mempool configurations" until he finds one configuration where the random function selects one of his own addresses to be the cosigner for his double spend transaction. If we're talking about a small altcoin, the attacker could easily create 90% of the mempool transactions, and be thus quite sure to be selected.
Regarding the origin of the coins, this problem imo is solvable: just start with a PoW phase at the start and then change to the new consensus -- if you can make it work.
I have to disagree with your assessment. The number of Bitcoin UTXOs has been climbing consistently, which means that the number of outputs has been consistently greater than the number of inputs.
A possible solution might be to require a transaction to cosign only one input for all of its outputs. However, that might create the reverse problem of not having enough transactions to cosign all the inputs (because there are more inputs than transactions). Perhaps the solution is to require a transaction to cosign a number of other inputs equal to the number of its inputs.
That would mean, that the initial Proof of Work is the only thing, protecting the whole system. Because then, someone could make a different alternative chain, where initial Proof of Work will be bigger than previously, and then effortlessly make any signatures on top of that. Which means, that the whole consensus would be again "obscured Proof of Work", where instead of targetting current signatures, attackers could target the initial Proof of Work, before the switch to staking.
And if you make the initial Proof of Work impossible to overwrite by consensus rules, then it doesn't matter, if it will be there or not. Then, it will be just a full Proof of Stake, and it doesn't really matter that much, how you will pick initial owners, if "51% once, 51% forever" will still be true after transition to signature-based system. Of course, instead of having 51% coins, your consensus could assume 51% cosigners, but it will only make things easier to attack, than existing Proof of Stake systems.
Not only that: it doesn't have any upper value. It is not limited by any consensus rules, so people can endlessly make new UTXOs. And in your consensus, there are no protections from making more outputs than needed, just to increase chances of being selected.
In existing chains? Yes. But in your consensus, there is no incentive to do that, if they can sign more things by owning more UTXOs. Quite the opposite: everyone has an incentive to make UTXO set explode, and produce more UTXOs, than everyone else.
I have few thoughts and questions.
1. This proposal reminds of how some DAG-based cryptocurrency works. When creating a TX on those cryptocurrnecy, you're required to verify few TX chosen by deterministic and verifiable random function.
2. Since the TX need to include list of cosigner, wouldn't it bloat the RAM and storage drive?
Considering majority people don't bother run their own Bitcoin node or have server that online 24/7, it makes me wonder how many times the sender must repeat such process.
I just want to say thanks for all the insights and criticisms. In response, I have made substantial changes to the protocol. Check it out and let me know what you think.
I see you updated the OP, @SapphireSpire. But I don't see how the changes really solve the problems pointed out.
Again, there is no global mempool, so it's the nodes themselves who select the "big list of addresses". And that continues to be the problem here. There is no way to prove a transaction was broadcasted. All ways to achieve this can be sybil attacked (or involve traditional byzantine fault proof algorithms, like PBFT, or PoW or a similar mechanism).
What's the "highest address"? The address with the oldest output perhaps? Still the node of the attacker compiles the list, not some "global entity". So again -- they can "grind" through different configurations and eventually they'll reach a state where they can sign a double spend transaction.
What you would need is some interactive mechanism where you can ensure that really different nodes interact with each other which are not from the same entity. And there you'll probably need PoS or PoW to achieve this via incentives.
I don't see how that changes the problem described above.
Let's see how a double spend attack would be carried out in that protocol:
- Attacker pays to merchant.
- In that payment, the attacker ensures that he's the only one who co-signs the payment with one of his addresses. He can compile as many lists as he wants.
- Attacker gets the (virtual) good he wants to purchase, or if the victim is an exchange withdraws everything via cryptocurrency.
- Now the attacker builds a new transaction with the same UTXO. Again he ensures that the list only contains cosigning addresses of his own nodes. Again he can complile as many lists as he wants.
- The attacker deletes all remnants of the old transaction and its cosigners from his nodes. There may be other nodes, apart from the victim's node, still having the old transaction in their database. But the attacker simply tries to outnumber these nodes via a sybil attack, so the new transaction becomes part of the "consensus".
The sybil attack in the last step is the problem PoW (and at least partly PoS) solve, and that's what's missing in the protocol.
@stwenhao: If the protocol doesn't work on its own, then you're correct, the lineage back to genesis via PoW would then be the only protection. But in my post I referred to the (unlikely) situation that the protocol works.
Sybil attacks are used to subvert reputation and voting systems. The random selection of addresses into priority lists is not a reputation or voting system. As long as the opportunity to cosign transactions is randomly distributed, and the network can never be stuck or fooled by any of the choices the cosigner makes, it doesn't really matter who makes the choice. No number of nodes you control or addresses you have in the mempool is going to empower you to force or fool other nodes into accepting invalid transactions.
If you don't KYC every single address, then you don't know, if address A and address B are both owned by the same person or not. And if someone can make decisions about the validity of its own coins, then how other people can trust the system, if anyone can sign anything in practice?
This is exactly, what could happen in practice, if you would release the code, working as described. Of course, even more likely scenario is just simple pump and dump, without any serious attacks, because it will be more profitable to attack the exchange rate directly, if your coins will be created from scratch, instead of being connected with existing ones, which already have more stable position.
But then, it goes back to what I previously said about Proof of Work: it is not detached from your system. It is only hidden in different places. If you move classical block header mining into grinding the order of addresses to cosign instead, then it will still be based on Proof of Work, but just less people will know, how your system works, and more of them will be fooled by the smarter ones, who will abuse holes in the protocol.
And then, if Proof of Work is needed anyway, then why do you want to hide it?
I didn't refer to the process of the priority list creation as the phase where the sybil attack would occur. From my interpretation of your protocol, it would be a P2P network like Bitcoin. Thus the priority list creation is something every user can control at his own will because it happens at his own node's mempool -- and that includes attackers.
The attacker can decide at will to include or exclude transactions made by other users. Because nobody can check that the user already "saw" a transaction and discarded it (in this case he could decide to ban the node for foul play). Maybe the attacker should include at least some "external" transactions to be able to fool other nodes easier, but if the number of own addresses is high enough he will with almost 100% probability find a configuration where he's his own co-signer.
The sybil attack referred to a later step of the attack: when the attacker has already submitted the double spend transaction and cosigned it. He must then lure the other nodes into accepting that transaction and discard the previous transaction where he paid the merchant/exchange. For this step, the sybil attack would be handy: he can spawn hundreds or thousands of nodes (for example with a botnet), "infecting" the network with the double spend transaction.
The nodes are presented with two different histories at that point, which both look legitimate from their point of view. And some "voting" would probably go on in this phase for the nodes to select one. If a node connects to lots of other nodes and they're transmitting them the double spend history, then they eventually would "reorganize" their database.
BTW: I admit that I had that flawed view of a "global mempool" too during some time, and thus I thought something like PoS was much easier to develop than it really was ...
Indeed one could describe such a system as an "obfuscated proof of work", but it's much less formalized than Bitcoin's PoW, so it will be probably always unstable. There may be periods with few active connected nodes, and these would create opportunities for attackers.
In the unlikely event that an attacker manages to flood the mempool with so many of his own addresses that he ends up owning all of the addresses in the priority list of an output that he also owns, despite random selection, he can try to double spend it. If he cosigns his transactions before he publishes them, they will be invalid and not even propagate. He must publish his signed transactions before he can cosign them, so everyone can see them. As soon as he cosigns one, the others are invalidated. If he cosigns more than one, he merely locks up his coins until he resolves the conflict, either by redacting all but one transaction, or by using one of the other addresses on his list to cosign just one of them. All that work for nothing because he only earns the fee cosigning other user's transactions.
But this is exactly the problem I'm trying to explain all the time: there is no way (without PoS or such a system, or PoW and blocks) to prove that he hasn't published all transactions and thus "misbehaved".
Nodes are independent one from another in a P2P network, there is no global mempool which can compared with the "published" transactions. Every node has his own mempool which differs from other mempools, because they query transactions one from another all the time and don't have the same "view".
To get a global view of the mempool, you need a system which decides which transactions are part of that global mempool. That can't be an open system, because otherwise all the time attackers will be trying to manipulate it.
If there was PoS for example, you could build a system where a node can only carry out transactions that also in the mempools of the stakers. AFAIK Obyte (formerly known as Byteball) works this way: it has no traditional blocks, but the stakers check all the time that the transactions in their mempools are not conflicting and go back to some "anchor" transaction, and thus they can rely on a system relatively similar to your "cosigning" protocol.
This also doesn't work, because of a similar reason. He cosigns the original transaction to the victim and then would wait until a big number of other nodes would also think this transaction is legit, so the victim sends him the value, asset or cryptocurrency he wants to steal.
Only when that has happened, he starts his sybil attack with the double spend transaction. This means the conflict arises after the attacker has already stolen the good he wanted to steal (this is not different in a Bitcoin 51% attack, by the way). Now the network will try to resolve the conflict, but when the attacker has a high enough number of nodes, he can trick other nodes into accepting the double spend transaction. He is the cosigner of both (only with different addresses), so he can simply delete the signature of the first one on his nodes, and all other nodes the attacker spawned would pretend they have never seen that transaction. The address that co-signed the first transaction? This node simply disappears.
The most likely way to achieve this, as already wrote, is a botnet. Of course the attack would not be cheap. But if there is more value in the network than the cost of the attack, then it can (and will eventually) be stolen.