Bitcoin Forum
May 05, 2024, 11:02:19 PM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: « 1 2 3 4 [5] 6 »  All
  Print  
Author Topic: A successful DOUBLE SPEND US$10000 against OKPAY this morning.  (Read 123957 times)
oakpacific
Hero Member
*****
Offline Offline

Activity: 784
Merit: 1000


View Profile
March 13, 2013, 10:28:06 AM
Last edit: March 13, 2013, 10:46:33 AM by oakpacific
 #81

Currently the merchant just polls the transaction for the number of confirmations.  The client never says "this one is non-reversible".  This kind of monitoring system would require the client to make a judgement call.

I don't think you even need to change the client, it's about if the merchant delivers the final goods or not, so it could be an additional system that just checks the blockchain for possible forks.

it's not quite that simple: which blockchain?

The simplest way is to  just query a third party, e.g., blockchain.info's API, I am sure there are many other methods, to those who are on the orphaned chain, the main chain is just their orphaned chain, you only need to decide if there is a big difference between the two chains, no need to decide which one is right.

https://tlsnotary.org/ Fraud proofing decentralized fiat-Bitcoin trading.
There are several different types of Bitcoin clients. The most secure are full nodes like Bitcoin Core, but full nodes are more resource-heavy, and they must do a lengthy initial syncing process. As a result, lightweight clients with somewhat less security are commonly used.
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction.
luv2drnkbr
Hero Member
*****
Offline Offline

Activity: 793
Merit: 1016



View Profile
March 14, 2013, 02:12:13 AM
 #82

Currently the merchant just polls the transaction for the number of confirmations.  The client never says "this one is non-reversible".  This kind of monitoring system would require the client to make a judgement call.

I don't think you even need to change the client, it's about if the merchant delivers the final goods or not, so it could be an additional system that just checks the blockchain for possible forks.

it's not quite that simple: which blockchain?

the longest one.  that's always the main chain.  that's why the two forks were called the 0.8 chain and the 0.7 chain.  chains that aren't the longest are the forks.  for a while the 0.7 chain was the fork until miners agreed with gavin that they should switch to it.  then it became the longest.

AndrH
Newbie
*
Offline Offline

Activity: 7
Merit: 0


View Profile
March 14, 2013, 11:53:44 AM
 #83

Yes we resolved this situation.

Happy end =)
matt4054
Legendary
*
Offline Offline

Activity: 1946
Merit: 1035



View Profile
March 14, 2013, 12:45:29 PM
 #84

I was wondering if this was the reason why OKPAY has still not resumed Bitcoin operations since the fork, while others already have?

I use OKPAY services including Bitcoin on a regular basis and I would hate that such events have long term consequences on OKPAY operations as well as other payment providers.
Piper67
Legendary
*
Offline Offline

Activity: 1106
Merit: 1001



View Profile
March 14, 2013, 03:10:45 PM
 #85

Yes we resolved this situation.

On behalf of those of us wanting to use OKPAY and Bitcoin, please don't let the wilful actions of one individual affect your operations too much. By his own admission, he attempted a double spend once he saw what was happening... clearly, a hard fork is not desirable, but the last time there was one was in 2010 (technically, orphaned blocks happen all the time and could be considered mini forks, but we're talking about one that went beyond six confirmations).
paraipan
In memoriam
Legendary
*
Offline Offline

Activity: 924
Merit: 1004


Firstbits: 1pirata


View Profile WWW
March 14, 2013, 05:15:59 PM
Last edit: March 14, 2013, 10:52:35 PM by paraipan
 #86

Yes we resolved this situation.

Nice to hear that.

To prevent this happening again in the future consider implementing "bitcoind alerts", and do automatic emergency stop on all bitcoin transactions if an alert ever shows up. It's an elegant and easy way to be warned by the community, and with enough time to avoid being "double-spent".

BTCitcoin: An Idea Worth Saving - Q&A with bitcoins on rugatu.com - Check my rep
Stephen Gornick
Legendary
*
Offline Offline

Activity: 2506
Merit: 1010


View Profile
March 14, 2013, 09:24:25 PM
Last edit: March 14, 2013, 11:01:59 PM by Stephen Gornick
 #87

I later manually corrected the issue with another transaction, thus double spend.

For post-mortem analysis, would you mind sharing how that raw transaction was broadcast?  Through bitcoin-Qt/bitcoind I presume?   But was this just connecting to peers or had you actually explicitly connected to a mining pool or well connected node?

The question is that most peers would have rejected it because they should already have known of the original transaction (12814b8ad57ce5654ba69eb26a52ddae1bff42093ca20cef3ad96fe7fd85d195) and not relayed your double spend (762443f6373b7c8b3833d4ad23578fc3099cc29b86d1359d0c0565e3c8614f91).  

With all the nodes reverting to 0.7 and/or starting up with an empty memory pool it is not impossible for your node to have reached one of them with no knowledge of the original transaction and then because your double spend transaction was perfectly valid for that node to relay your transaction got relayed to other new nodes as well.  Eventually then there would be a path that would reach the miner who eventually mined 225466 (the block with the double spend) -- BTC Guild [Edit: Yes, confirmed BTC Guild, per the coinbase].

Unichange.me

            █
            █
            █
            █
            █
            █
            █
            █
            █
            █
            █
            █
            █
            █
            █
            █


JeromeS
Newbie
*
Offline Offline

Activity: 55
Merit: 0


View Profile
March 15, 2013, 01:14:14 AM
 #88

Been meaning to do this since The Night of the Two Chains, finally got the time to do it today.

A list of all transactions included in the .8 fork but not the (current) main chain. i.e. possible double spends.
270 transactions out of 11914 fit that description (2.26%).


(got the data from here, for some reason that page doesn't work anymore)

I might go through all of these later and try to find any "special" ones. For now though I have to study... : /


p.s. sorry for the huge post. [spoiler] tag not working. how do I spoiler stuff on this forum ?
macbook-air (OP)
Sr. Member
****
Offline Offline

Activity: 324
Merit: 260


View Profile WWW
March 15, 2013, 02:02:08 AM
Last edit: March 15, 2013, 02:21:27 AM by macbook-air
 #89

I later manually corrected the issue with another transaction, thus double spend.

For post-mortem analysis, would you mind sharing how that raw transaction was broadcast?  Through bitcoin-Qt/bitcoind I presume?   But was this just connecting to peers or had you actually explicitly connected to a mining pool or well connected node?

The question is that most peers would have rejected it because they should already have known of the original transaction (12814b8ad57ce5654ba69eb26a52ddae1bff42093ca20cef3ad96fe7fd85d195) and not relayed your double spend (762443f6373b7c8b3833d4ad23578fc3099cc29b86d1359d0c0565e3c8614f91).  

With all the nodes reverting to 0.7 and/or starting up with an empty memory pool it is not impossible for your node to have reached one of them with no knowledge of the original transaction and then because your double spend transaction was perfectly valid for that node to relay your transaction got relayed to other new nodes as well.  Eventually then there would be a path that would reach the miner who eventually mined 225466 (the block with the double spend) -- BTC Guild [Edit: Yes, confirmed BTC Guild, per the coinbase].


Code:
$ git diff src/rpcrawtransaction.cpp
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index e634ed7..1f045e8 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -164,8 +164,6 @@ Value listunspent(const Array& params, bool fHelp)
             CBitcoinAddress address(input.get_str());
             if (!address.IsValid())
                 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+input.get_str());
-            if (setAddress.count(address))
-                throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+input.get_str());
            setAddress.insert(address);
         }
     }
@@ -520,9 +518,11 @@ Value sendrawtransaction(const Array& params, bool fHelp)
     {
         // push to local node
         CTxDB txdb("r");
-        if (!tx.AcceptToMemoryPool(txdb))
-            throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX rejected");
-
+        if (!tx.AcceptToMemoryPool(txdb)) {
+            SyncWithWallets(tx, NULL, true);
+            RelayMessage(CInv(MSG_TX, hashTx), tx);
+            throw JSONRPCError(RPC_DESERIALIZATION_ERROR, string("TX rejected, relay anyway ")+hashTx.GetHex());
+        }
         SyncWithWallets(tx, NULL, true);
     }
     RelayMessage(CInv(MSG_TX, hashTx), tx);
$ bitcoin createrawtransaction '[{"txid": "e6ee06cec15f8fab2c1aa81037e6ba9b1d7c7c4073a2795e847aa9ca5b84daf1", "vout": 1}]' '{"1J1F3U7gHrCjsEsRimDJ3oYBiV24wA8FuV": 137.35368622}'
0100000001f1da845bcaa97a845e79a273407c7c1d9bbae63710a81a2cab8f5fc1ce06eee60100000000ffffffff01ae17b132030000001976a914ba85dc466140d3ef2eac3f7e42088ec501315a4b88ac00000000
$ bitcoin signrawtransaction 0100000001f1da845bcaa97a845e79a273407c7c1d9bbae63710a81a2cab8f5fc1ce06eee60100000000ffffffff01ae17b132030000001976a914ba85dc466140d3ef2eac3f7e42088ec501315a4b88ac00000000 '[{"txid": "e6ee06cec15f8fab2c1aa81037e6ba9b1d7c7c4073a2795e847aa9ca5b84daf1", "vout": 1, "scriptPubKey": "76a914ba85dc466140d3ef2eac3f7e42088ec501315a4b88ac"}]'
{
    "hex" : "0100000001f1da845bcaa97a845e79a273407c7c1d9bbae63710a81a2cab8f5fc1ce06eee6010000008c493046022100d6e0dec64778c669a4869a73dc057959ac6f8c6fa390e9ceb03bb040d3eb0933022100f3dc55dccbde883e7aadf737a5d8531847fdab1cc2b80a2357ce5dc5378a8485014104054f0d458c4dc3d0a4bb35cd17e624eb76ea99b702561bd0bea0aefe34c6c860fafca4faae957bb009e0ece9cba07cccd30dc008512a9a3021dbcfd2127938fcffffffff01ae17b132030000001976a914ba85dc466140d3ef2eac3f7e42088ec501315a4b88ac00000000",
    "complete" : true
}
$ bitcoin createrawtransaction '[{"txid": "b53cbbf160f1a5c470dba13672338908c5c9099985f6fdc37d44a5facae957df", "vout": 1}]' '{"1J1F3U7gHrCjsEsRimDJ3oYBiV24wA8FuV": 62.64371378}'
0100000001df57e9cafaa5447dc3fdf6859909c9c50889337236a1db70c4a5f160f1bb3cb50100000000ffffffff01b2b86275010000001976a914ba85dc466140d3ef2eac3f7e42088ec501315a4b88ac00000000
$ bitcoin signrawtransaction 0100000001df57e9cafaa5447dc3fdf6859909c9c50889337236a1db70c4a5f160f1bb3cb50100000000ffffffff01b2b86275010000001976a914ba85dc466140d3ef2eac3f7e42088ec501315a4b88ac00000000 '[{"txid": "b53cbbf160f1a5c470dba13672338908c5c9099985f6fdc37d44a5facae957df", "vout": 1, "scriptPubKey": "76a914ba85dc466140d3ef2eac3f7e42088ec501315a4b88ac"}]'
{
    "hex" : "0100000001f1da845bcaa97a845e79a273407c7c1d9bbae63710a81a2cab8f5fc1ce06eee6010000008c493046022100d6e0dec64778c669a4869a73dc057959ac6f8c6fa390e9ceb03bb040d3eb0933022100f3dc55dccbde883e7aadf737a5d8531847fdab1cc2b80a2357ce5dc5378a8485014104054f0d458c4dc3d0a4bb35cd17e624eb76ea99b702561bd0bea0aefe34c6c860fafca4faae957bb009e0ece9cba07cccd30dc008512a9a3021dbcfd2127938fcffffffff01ae17b132030000001976a914ba85dc466140d3ef2eac3f7e42088ec501315a4b88ac00000000",
    "complete" : true
}
$ while true; do bitcoin sendrawtransaction 0100000001f1da845bcaa97a845e79a273407c7c1d9bbae63710a81a2cab8f5fc1ce06eee6010000008c493046022100d6e0dec64778c669a4869a73dc057959ac6f8c6fa390e9ceb03bb040d3eb0933022100f3dc55dccbde883e7aadf737a5d8531847fdab1cc2b80a2357ce5dc5378a8485014104054f0d458c4dc3d0a4bb35cd17e624eb76ea99b702561bd0bea0aefe34c6c860fafca4faae957bb009e0ece9cba07cccd30dc008512a9a3021dbcfd2127938fcffffffff01ae17b132030000001976a914ba85dc466140d3ef2eac3f7e42088ec501315a4b88ac00000000; sleep 10; bitcoin sendrawtransaction 0100000001f1da845bcaa97a845e79a273407c7c1d9bbae63710a81a2cab8f5fc1ce06eee6010000008c493046022100d6e0dec64778c669a4869a73dc057959ac6f8c6fa390e9ceb03bb040d3eb0933022100f3dc55dccbde883e7aadf737a5d8531847fdab1cc2b80a2357ce5dc5378a8485014104054f0d458c4dc3d0a4bb35cd17e624eb76ea99b702561bd0bea0aefe34c6c860fafca4faae957bb009e0ece9cba07cccd30dc008512a9a3021dbcfd2127938fcffffffff01ae17b132030000001976a914ba85dc466140d3ef2eac3f7e42088ec501315a4b88ac00000000; sleep 10; done
15e8729f4632f9542790e12e7e6891ac42ca9d109c38656e7259b58ee9133d2e
22b85b88ac4f18afaab9c06ee70b47df7da23201bd2ad646ca0b202d775aa999
15e8729f4632f9542790e12e7e6891ac42ca9d109c38656e7259b58ee9133d2e
22b85b88ac4f18afaab9c06ee70b47df7da23201bd2ad646ca0b202d775aa999
15e8729f4632f9542790e12e7e6891ac42ca9d109c38656e7259b58ee9133d2e
22b85b88ac4f18afaab9c06ee70b47df7da23201bd2ad646ca0b202d775aa999
......

(I cannot remember whether the last command returns simply txid or "error: {"code":-22,"message":"TX rejected, relay anyway txid"})

No. My fully synced bitcoind refused to execute any commands except getinfo. It simply reports error message: "Warning: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade." and exit.

So I had to set up a new bitcoind in Parallels Desktop's Ubuntu virtual machine and this bitcoind was not yet fully synced with the network. And it shouldn't have many connections as it was behind NAT.

Yurock
Sr. Member
****
Offline Offline

Activity: 462
Merit: 250


View Profile
April 17, 2013, 09:30:32 AM
 #90

Maybe the problem it that there is one implementation (bitcoind / bitcoin-qt) that decides what is right and what is not for the majority of the network. Bitcoin relies on a state when the vast majority of the network agree on the rules. That may not be the case when a single bug affects a large portion of the network. Under these conditions the whole proof of work mechanism becomes unreliable.

If we had a variety of implementations, a bug in one of them would have much smaller impact. Only users of the buggy client would be required to upgrade. We would not have to take the generally wrong way of downgrading to a buggy version.
arklan
Legendary
*
Offline Offline

Activity: 1778
Merit: 1008



View Profile
April 17, 2013, 09:37:52 AM
 #91

Maybe the problem it that there is one implementation (bitcoind / bitcoin-qt) that decides what is right and what is not for the majority of the network. Bitcoin relies on a state when the vast majority of the network agree on the rules. That may not be the case when a single bug affects a large portion of the network. Under these conditions the whole proof of work mechanism becomes unreliable.

If we had a variety of implementations, a bug in one of them would have much smaller impact. Only users of the buggy client would be required to upgrade. We would not have to take the generally wrong way of downgrading to a buggy version.

this is why the discussion of a "bitcoin spec" is ongoing and of worth. check the dev sub forum.

i don't post much, but this space for rent.
Bitcoinpro
Legendary
*
Offline Offline

Activity: 1344
Merit: 1000



View Profile
April 17, 2013, 11:51:43 AM
 #92

Just received a telephone call from OKPAY. The double spend money has been refunded to them. They promise me to send me my 64.xxx BTC within 15 minutes after they receive my refund. Please see if they respect their promise: 1J1F3U7gHrCjsEsRimDJ3oYBiV24wA8FuV This address should receive 64.xxx BTC before 09:30 UTC.



This is not the way to do customer service. If not this incident, I don't know when they start to care me and return me the 64.xxx BTC.

why is ok support using a comma and decimal point in the same post

WWW.FACEBOOK.COM

CRYPTOCURRENCY CENTRAL BANK

LTC: LP7bcFENVL9vdmUVea1M6FMyjSmUfsMVYf
Raoul Duke
aka psy
Legendary
*
Offline Offline

Activity: 1358
Merit: 1002



View Profile
April 17, 2013, 12:18:45 PM
 #93

why is ok support using a comma and decimal point in the same post

Probably both values copy pasted from previous messages or one of them c/p and the other written by the support person.
jl2012
Legendary
*
Offline Offline

Activity: 1792
Merit: 1093


View Profile
April 08, 2014, 03:04:18 PM
 #94

It has been more than a year. I think this is the only instance of successful double spending of a 6-confirmation transaction. Have anything been done to address this problem? Comparing with those fancy applications, this involves the very fundamental principle: transaction irreversibility. If it is not fixed, I am sure it will happen again when we have another unexpected fork and the harm could be much more serious.

Donation address: 374iXxS4BuqFHsEwwxUuH3nvJ69Y7Hqur3 (Bitcoin ONLY)
LRDGENPLYrcTRssGoZrsCT1hngaH3BVkM4 (LTC)
PGP: D3CC 1772 8600 5BB8 FF67 3294 C524 2A1A B393 6517
arklan
Legendary
*
Offline Offline

Activity: 1778
Merit: 1008



View Profile
April 08, 2014, 03:12:55 PM
 #95

It has been more than a year. I think this is the only instance of successful double spending of a 6-confirmation transaction. Have anything been done to address this problem? Comparing with those fancy applications, this involves the very fundamental principle: transaction irreversibility. If it is not fixed, I am sure it will happen again when we have another unexpected fork and the harm could be much more serious.

Because this required a fork, I don't think there's anything that can be done. I mean, the entire system of bitcoin relies on forks not occurring. I'm no Dev though, so don't take my word as law.

i don't post much, but this space for rent.
drawingthesun
Legendary
*
Offline Offline

Activity: 1176
Merit: 1015


View Profile
April 08, 2014, 03:16:04 PM
 #96

It has been more than a year. I think this is the only instance of successful double spending of a 6-confirmation transaction. Have anything been done to address this problem? Comparing with those fancy applications, this involves the very fundamental principle: transaction irreversibility. If it is not fixed, I am sure it will happen again when we have another unexpected fork and the harm could be much more serious.

I wonder how it can be fixed?

Perhaps the client once seeing two similar chains is put into safe mode until an obvious longer chain emerges. Once one chain is perhaps 6 confirm ahead then automatically go out of safe mode and resume using the longest chain.

This solution would require no central control and can be automated by the nodes.

The important aspect would be the detection mechanism and watching two chains until there is a clear winner.
franky1
Legendary
*
Online Online

Activity: 4214
Merit: 4470



View Profile
April 08, 2014, 03:19:17 PM
 #97

It has been more than a year. I think this is the only instance of successful double spending of a 6-confirmation transaction. Have anything been done to address this problem? Comparing with those fancy applications, this involves the very fundamental principle: transaction irreversibility. If it is not fixed, I am sure it will happen again when we have another unexpected fork and the harm could be much more serious.

technically its not a double spend.. there is only one "receipt" of BTC that got confirmed on this main blockchain, meaning there is not 2 bunches of bitcoins that originated from one single bitcoin source on this main blockchain.

what happened is that businesses did not update the clients to be using the correct blockchain. thus the business does not see the correct transaction and ends out paying FIAT twice.

what needs to be done is to ensure forks dont happen, and in the small chance that a fork does occur, that businesses are not lazy about updating their clients, or double checking transactions before releasing different forms of funds or goods. (which would have prevented malleability issues if businesses had proper double checking methods in place)

there is not one single extra bitcoin on the blockchain that was cloned or not originate from a verified block reward. ill say it again a double spend is where 1 btc can be used twice. no coin has been used twice. all that has happened is that businesses have not had adequate checking processes in place. the bitcoin protocol and the blockchain does not show more confirmed coins then what has been released through blockchain rewards

I DO NOT TRADE OR ACT AS ESCROW ON THIS FORUM EVER.
Please do your own research & respect what is written here as both opinion & information gleaned from experience. many people replying with insults but no on-topic content substance, automatically are 'facepalmed' and yawned at
zolace
Sr. Member
****
Offline Offline

Activity: 364
Merit: 250


View Profile
April 08, 2014, 03:25:24 PM
 #98

All time UTC+08:00:

08:08 – Well before I knew what later have happened, I deposited $10000-worth Bitcoins to BTC-e over OKPAY's Bitcoin payment, I paid OKPAY address 12z2n8YCJw1BEsJhhQPLCTuLqwH341nKnE 211.9093 BTC and 0.0005 BTC as transaction fee.
09:30 – The transaction was included in version 0.8's fork, block 225446
10:08 – Deposit completed, $9800 credited to my BTC-e account
12:53 – After some study, I recognized, the transaction, though included in version 0.8's fork, was never confirmed by the pre-0.8 fork, so I decided to make two double spend transactions on two of the vins of the OKPAY transaction, and broadcasted them with the raw transaction API, 0.001 BTC transaction fee included in each transaction.
13:01 – The double spend transaction was included in pre-0.8 fork block 225446

You should know what happens next...

I bet merchants would think twice before they decide to accept Bitcoins after the incident.

well this is why there should be inventory watchers, and this is why there has to be someone to over look these transactions as this can be avoided.   

⚂⚄ Pocket Dice — Real dice experienceProvably Fair
Free BTC Faucet
⚅⚁
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
RodeoX
Legendary
*
Offline Offline

Activity: 3066
Merit: 1145


The revolution will be monetized!


View Profile
April 08, 2014, 03:28:31 PM
 #99

There has never been a double spend.

The gospel according to Satoshi - https://bitcoin.org/bitcoin.pdf
Free bitcoin in ? - Stay tuned for this years Bitcoin hunt!
Peter R
Legendary
*
Offline Offline

Activity: 1162
Merit: 1007



View Profile
April 08, 2014, 03:48:19 PM
Last edit: April 08, 2014, 04:04:25 PM by Peter R
 #100

It has been more than a year. I think this is the only instance of successful double spending of a 6-confirmation transaction. Have anything been done to address this problem? Comparing with those fancy applications, this involves the very fundamental principle: transaction irreversibility. If it is not fixed, I am sure it will happen again when we have another unexpected fork and the harm could be much more serious.

Like others have said, the same coin has never been spent twice in the history of bitcoin; when we say "double spend," we mean that someone thought they got paid but later found out that they didn't.  

There are many ways one can protect himself against such events.  In the case described in the OP, the event took place during a planned hard fork of the protocol.  If we feel it necessary to fork the code again (and we likely will), I think it would be wise for exchanges to require a full day of confirmations for large deposits.  Once it is clear that the fork was handled properly, services can reduce the confirmation requirements back to normal.  

Non-planned forks (large orphans) are rare. It is rarer still that the funds confirmed in the now-orphaned chain wouldn't also be confirmed in the new longest chain (it would strongly imply malicious intent, careful planning, and a large financial investment).  But one should still dynamically track confirmed coins and in the very very unlikely event that coins are not confirmed in the new chain, the service should immediately freeze the accounts in question.    

There is also nothing special about the number "6": personally, if I ran a large exchange I would likely require less than 6 confirmations for most deposits, but more than 6 for, say, 10 000 BTC.  

Run Bitcoin Unlimited (www.bitcoinunlimited.info)
Pages: « 1 2 3 4 [5] 6 »  All
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!