Technically the part the preserves double spending is Ring CT however by and large I see it lumped under Ring sigs when discussed.

Here's a link to the Ring CT papers. The original explains the base system, 2.0 formalises the security of the system, and 3.0 describes how the original protocols had issues and how they were improved.

Original Ring CT Paper: https://eprint.iacr.org/2015/1098

Ring CT 2.0: https://eprint.iacr.org/2017/921

Ring CT 3.0: https://eprint.iacr.org/2019/508

Personally I find the Ring CT 3.0 paper to be the most enlightening of these. For a simpler/shorter explanation however, Moneropedia has some videos that are helpful in this.

https://www.getmonero.org/resources/moneropedia/ringsignatur...

https://www.getmonero.org/resources/moneropedia/ringCT.html

-------

The key details are these.

Monero uses a UTxO (unspent transaction outputs) accounting model. There are a number of networks that use this model, namely Bitcoin. The UTxO model doesn't strictly have a concept of accounts but rather keys and UTxO. You can think of UTxO as as atomic chunks of data/value. These UTxO are created once and used once. If you want to spend money, your inputs are UTxO, the outputs are UTxO, and the balances of all of these inputs and outputs must sum up to a net 0. Now UTxO can only be spent if a valid cryptographic signature can be produced. If your private keys can produce that signature, the value held in that UTxO can be spent by you.

This gives us our three key points. All UTxO consumed or spent in a Tx must collectively sum up to zero, UTxO can only be spent if the proof object/cryptographic signature produced is valid, and UTxO can only be spent if they haven't yet been spent.

First Ring CT has each sender derive a one time private key from their private key and a one time public key derived from the recipient's public key. These keys are used to produce a set of encrypted "coins" which essentially hold the value of the UTxOs being spent and then created. This allows the sender and recipient to know the contents of the actual meaningful transaction. Then a cryptographic proof verifies that out of all the public keys in the Tx, all the keys can spend their selection of coins included in the Tx and only one of them is the real set of coins. From there the balance is verified by doing that some clever math where the sum of the encrypted outputs is divided by the sum of the encrypted inputs must equal some constant determined by the encryption key. This is a bit of a simplification but it works out such that it is equivalent to "ins - outs = 0" in a traditional UTxO system.

The key/signature verification mentioned previously has a nifty property where the produced "key images" serve as what are effectively "hashes" of the UTxO. This means that if any key image has previously been used in a transaction, it effectively guarantees that the corresponding UTxO has already been spent. Going back and checking this is somewhat more expensive than on a traditional network however optimisations (like using a bloom filter) allow for this check to run significantly faster.

That's how Monero upholds those 3 properties that are required for consistency in a UTxO based network without leaking information about the sender, recipient, or balances. In short it's using one time PKI derivations to break information symmetry and then from there structuring the encrypted data so that you can use some clever arithmetic and signature checks to verify correctness.

Apologies if my explanation isn't terribly clear or perfectly accurate. It's my reasonably solid understanding of the system. I'm not a formally trained cryptographer or mathematician so my choice of words or explanations may be somewhat inaccurate however they give a reasonable coverage of how the system works. If you want to dive more into the meat of it, I'd seriously recommend the Ring CT 3.0 paper as it's really well put together once you can get through the terse notation and dense amount of information.