Bitcoin Forum
May 06, 2024, 01:57:22 PM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
  Home Help Search Login Register More  
  Show Posts
Pages: « 1 ... 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 [58] 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 ... 186 »
1141  Bitcoin / Development & Technical Discussion / Re: Which clients fully support P2SH and/or multisig ? on: July 18, 2013, 04:18:28 PM
This example says that you need to satisfy a multisig with two keys, until the transaction reaches a certain depth, when it can be redeemed by one script.  The idea is that it removes the risk of the counterparty disappearing by giving the first guy the ability to reclaim his money in the future.

To be clear the protocol implemented now is that a time-locked refund tx is created when tx1 is created that returns the money in the future, but ultimately there will always be a short time window where the counter-party can vanish leaving the funds locked. Jeremy Spilman's solution was to have the counter-party also include some funds, so that their funds would be locked as well so the counter-party has strong incentives to not allow this to happen; I'm not sure what bitcoinj has implemented.

How can the counter-party vanishing affect this?  You get the refund (Tx2) signed by the payee before you (payor) sign the funding transaction (Tx1).   That essentially makes the whole operation atomic:  either all parties get their money into an escrow that automatically returns to the payor if one of the parties disappears... or nothing happens.
1142  Bitcoin / Development & Technical Discussion / Re: A question on ECDSA signing (more efficient tx signing)? on: July 18, 2013, 04:20:28 AM
Even if there is, a different piece of data is being signed for each input/key.  i.e. "Data to be signed, d" in your question above is not consistent.  Look up OP_CHECKSIG for details.
1143  Bitcoin / Armory / Re: Armory in Fedora 18 on: July 17, 2013, 06:15:43 PM
Changing the setting so it doesn't try to run bitcoin for me and then starting the daemon does seem to work.
What are the potential negatives of that?

Sorry for the delay in responding.  Got distracted by a bunch of things and missed this.

There is no negative.  The auto-bitcoind was intended to make things easier and smoother for less-experienced users, especially those with Bitcoin-Qt/bitcoind in standard locations or with it not installed yet (it will download and install it for you, in a cryptographically-secure manner).

The only difference running it yourself and letting Armory do it for you is convenience (and auto-bitcoind can definitely be less convenient if you have a non-standard setup).

I haven't tried it on Fedora, but you should see if the download&install works. I'm intensely curious to find out if it does.  I'm not aware of the regular version requiring root to run on Fedora. 

And yes, Armory currently latches onto the same blk*.dat files that bitcoin-qt/bitcoind is using.  However, indexing those files in RAM takes a lot of time and memory, which is why I hope to have a disk-based version in the next week or two.
1144  Bitcoin / Development & Technical Discussion / Re: Which clients fully support P2SH and/or multisig ? on: July 17, 2013, 06:07:00 PM
...we've found that micropayment channels don't need sequence numbers anyway, and the non-sequence-based version is far more secure too

Can you elaborate on this?  Or point me to where the technicals are described?  I was not aware of this development.
1145  Bitcoin / Armory / Re: Algorithm for going from a paper backup code to actual keys on: July 14, 2013, 06:34:46 PM
I know that in some variants/parameters of RS, you end up changing all the bytes, and you need an RS library to decode it.  I'd really prefer the code to simply be appended data (and I'm pretty sure there's a way to do it with RS).

I think the big benefit of RS is that it can correct runs of errors.  Things like parity checking can only handle a few bits at a time.

It is a finite field thing so it only works if you have a prime power as a mod (so your symbols could be base 2^8).  However, non-prime mods makes calculations harder.

You can do it without changing the data.  However, I am not sure if that breaks the error finding part of the correction.

The idea is that you create a polynomial that passes through all the points in your data (x, y) for (x = 0 to x = 63).  You then compute the value of the polynomial for x = 64 to 67, for 4 extra symbols.

When receiving you do the same thing.  If the extra bytes fall on the polynomial that shows there is no errors.

If 3 of the 4 are on the polynomial, then that means that one of them is probably wrong.  You have 67 out of 68 agreement on the answer.

If they are all wrong, then some of the errors are in the main data.

You then need to find which ones are wrong.  This is where all the various mappings come into it.

Ahh, very cool.  Very similar to Shamir's Secret Sharing.  I implemented the finite-field math in Armory to do SSS but it's extremely ineffiicient and was more of an exercise in highly SLOC-efficient arbitrary-integer math in python (it's basically all list comprehensions and recursion... extremely compact).  It is in the "backupcenter" branch which will hopefuly be merged soon.  But I never quite figured out how to do it with arbitrary data, since I can't use 28 since it's not a prime.

Is there a composite prime (p*q) such that (p-1)*(q-1) == 256?  Seems like that would work.  But I'm also not here to reinvent anything, I'm just curious for my own mathematical understanding (I'm not familar with RS at all before now).

EDIT: Of course there is:  p=q=17, leads to a finite field with modulus 289, and should have (17-1)*(17-1) = 256 elements. EDIT2: oops, p and q have to be different... nm
1146  Bitcoin / Armory / Re: Algorithm for going from a paper backup code to actual keys on: July 14, 2013, 01:32:01 PM
Indeed.  Two errors is kinda tough to deal with.  But that's why there's also a WalletID check after you're done entering stuff.  So even if Armory corrects wrong, the user manually error-checks the result.

By the way, this isn't exactly "CRC".  It's just the simple error correction used in addresses.   However, I'll be updating the backup stuff soon (feel free to checkout the backupcenter branch and test it for me!).  I don't see why I can't switch the error catching code.  I had wanted to do Reed-Solomon, but I didn't want to pull in a huge extra library for it (and I didn't find a lot of good ones in python).  RS in C++ would be easy to pull in through SWIG, so that would work if I needed it.    My only requirement for the error-correcting code is that the original data be unmodified.  I know that in some variants/parameters of RS, you end up changing all the bytes, and you need an RS library to decode it.  I'd really prefer the code to simply be appended data (and I'm pretty sure there's a way to do it with RS).
1147  Bitcoin / Development & Technical Discussion / Re: Which clients fully support P2SH and/or multisig ? on: July 12, 2013, 06:06:29 PM
I'm reading Satoshi client code and Bitcoinj code. It seems to me that Satoshi supports given a P2SH address as destination, while Bitcoinj does not. On the other side, Satoshi client does not seems to provide multisig in its user interface.

Armory seems to support multisigs natively, but I cannot find support for P2SH (maybe is there somewhere).

Does anybody have a support matrix for each feature and each client ?

That would be awesome.

Thanks! Sergio.



Armory has a ton of code for interpretting and handling multi-sig scripts, but nothing is actually usable yet.  It was implemented before P2SH existed (you might even find references in the code to OP_EVAL, which was the precursor to P2SH, and what was the leading contender when I wrote that code).

Armory needs a new wallet format in order to handle any of this "new" stuff.  Also, the blockchain utilities do not handle P2SH scripts.  This is all getting implemented in the next two major versions -- the first with new blockchain utilities for persistent DB storage, and the second with the new wallet format.  But I wouldn't consider anything "supported" yet, except Pay2PubkeyHash and Pay2PubKey scripts.
1148  Bitcoin / Development & Technical Discussion / Re: [Feat Request] - Solution for Lost Wallet Passphrase on: July 11, 2013, 05:23:14 PM
Use Armory.  Print a paper backup.  Keep it in a safe place.

Armory never reuses addresses.  All change always goes to the next address in your infinite list of addresses backed up by your paper backup.  It's the "right way", as evidenced by the fact that BIP 32 is basically an extension of that that will eventually used in Bitcoin-Qt and other alt clients.
Are serialized BIP32 keys interoperable with Armory? If not yet, is it planned?

I am about 70% done with the new wallet format that will accommodate all sorts of new stuff, including BIP 32.  I plan to standardize the wallet operations to BIP 32 as closely as possible, for interoperability.  But I got distracted by some the RAM issues and am working on that right now.  As soon as I'm done, I'll be upgrading the wallets.
1149  Bitcoin / Development & Technical Discussion / Re: [Feat Request] - Solution for Lost Wallet Passphrase on: July 11, 2013, 02:17:35 PM
Use Armory.  Print a paper backup.  Keep it in a safe place.

Armory never reuses addresses.  All change always goes to the next address in your infinite list of addresses backed up by your paper backup.  It's the "right way", as evidenced by the fact that BIP 32 is basically an extension of that that will eventually used in Bitcoin-Qt and other alt clients.
1150  Bitcoin / Development & Technical Discussion / Re: [BOUNTY: 0.3 BTC/person] Help test Armory backups demo (M-of-N GUI + More) on: July 10, 2013, 02:46:26 PM
Hey Alan, what's the status of this branch. Can these features be used on prodnet yet?

They were going to be merged into the new version that includes the persistent blockchain updates, though that update has been slower (and I've been more distracted) than I expected. 

However, it does still need some more testing... sounds like you are volunteering Smiley
1151  Bitcoin / Armory / Re: Algorithm for going from a paper backup code to actual keys on: July 09, 2013, 11:26:25 PM
The persistent blockchain stuff will solve about 27 problems all at once, and also improve flexibility in that respect.

So, there will be 2 full databases of the blockchain, or is the plan to drop bitcoind as verifier?

For the first version, there will be two full databases.  Then once that's stable (because that's easiest, and has some other uses), then I will implement a partial-DB version which will store just a fraction of the data.  In the future that will include pruning, too.  Though, pruning is being bypassed for now (though I'm putting the hooks in) because I rely on having the history to produce the full transaction ledger.  I can't turn on pruning until the wallet (or some other file) starts storing that history.
1152  Bitcoin / Armory / Re: Algorithm for going from a paper backup code to actual keys on: July 09, 2013, 11:09:21 PM
Slightly off topic, have you seen this commit.

It allows raw block dumps over the RPC interface (to/from hex strings).  Would that be worth using to save you from having to manually read the files from the disk?

Armory doesn't even use the RPC interface, unless you use the auto-bitcoind feature.  It communicates with bitcoind/bitcoin-qt as a peer (over localhost).  So "getblock" messages have always been available to Armory, it just hasn't been needed yet.  Armory doesn't store the whole blocks, it only saves the block and tx hashes and where to find that data in the blk*.dat files.  Thus, I have no choice but to scan the blockfiles.

However, the "persistent blockchain" stuff will change that.  Now Armory will maintain it's own block database, and I will no longer have any reliance on blk*.dat files.  In fact,  switching to getblock network messages was exactly how I was planning to get the data.  It's because direct reliance on blk*.dat files has caused countless problems, in addition to forcing bitcoind/bitcoin-Qt to have to be run on the same system running Armory (though some users made it work remotely using network mounts, like sshfs).  The persistent blockchain stuff will solve about 27 problems all at once, and also improve flexibility in that respect.

But of course, it's a lot... of ... work...
1153  Bitcoin / Armory / Re: Algorithm for going from a paper backup code to actual keys on: July 09, 2013, 09:49:19 PM
Thanks.

I didn't realise that the info was so direct.  I thought you did some post processing to go from the info in the paper wallet to the actual wallet keys.  I guess that's a waste since the paper wallet has no protection.

You do have a system for the "printer-safe" version?

So, basically, for the paper wallets;

Each line is a hex string (with different letter to number mappings)
36 letters = 32 (value) + 4 (hash)

This means that an error will be missed one time in 65536, since the hash is 2 bytes, so the checking the wallet id is important.

If the CRC mismatches, it tries every possible value for each letter, keeping the others constant, and rechecks the hash.  This fixes 1 letter errors.

This is 16 bytes per line which give 32 bytes each for the chain code and private key.

Do you object to people using the system for other software?

Oh, that was just the deterministic wallet algorithm.  The code for actually converting the paperbackup info to the PrivKey(0) and Chaincode is:

Code:
###### Typing-friendly Base16 #####
#  Implements "hexadecimal" encoding but using only easy-to-type
#  characters in the alphabet.  Hex usually includes the digits 0-9
#  which can be slow to type, even for good typists.  On the other
#  hand, by changing the alphabet to common, easily distinguishable,
#  lowercase characters, typing such strings will become dramatically
#  faster.  Additionally, some default encodings of QRCodes do not
#  preserve the capitalization of the letters, meaning that Base58
#  is not a feasible options
NORMALCHARS  = '0123 4567 89ab cdef'.replace(' ','')
EASY16CHARS  = 'asdf ghjk wert uion'.replace(' ','')
hex_to_base16_map = {}
base16_to_hex_map = {}
for n,b in zip(NORMALCHARS,EASY16CHARS):
   hex_to_base16_map[n] = b
   base16_to_hex_map[b] = n

def binary_to_easyType16(binstr):
   return ''.join([hex_to_base16_map[c] for c in binary_to_hex(binstr)])

def easyType16_to_binary(b16str):
   return hex_to_binary(''.join([base16_to_hex_map[c] for c in b16str]))


def makeSixteenBytesEasy(b16):
   if not len(b16)==16:
      raise ValueError, 'Must supply 16-byte input'
   chk2 = computeChecksum(b16, nBytes=2)
   et18 = binary_to_easyType16(b16 + chk2)
   return ' '.join([et18[i*4:(i+1)*4] for i in range(9)])

def readSixteenEasyBytes(et18):
   b18 = easyType16_to_binary(et18.strip().replace(' ',''))
   b16 = b18[:16]
   chk = b18[ 16:]
   b16new = verifyChecksum(b16, chk)
   if len(b16new)==0:
      return ('','Error_2+')
   elif not b16new==b16:
      return (b16new,'Fixed_1')
   else:
      return (b16new,None)

The SecurePrint stuff hasn't been released yet, but the basis of it is here.  It's a 56-bit random key with an 8-bit checksum, forced through the same KDF that is used for wallet encryption.  But it uses a hardcoded 16 MB of RAM to guarantee sufficient stretching.  On my i5-2500k that it takes a little over 0.5s to stretch the SecurePrint key into the encryption key.   I questioned whether 56-bits was sufficient, but I needed to avoid having a key that was as long as the data it was protecting (BIP 32 will use only a 128-bit seed, so the SecurePrint code is half of that).  Given the stretching, I determined that it was. 
1154  Bitcoin / Armory / Re: Algorithm for going from a paper backup code to actual keys on: July 09, 2013, 07:47:14 PM
The code that does it is here:

https://github.com/etotheipi/BitcoinArmory/blob/master/cppForSwig/EncryptionUtils.cpp#L672

Unlike BIP 32, each private key is dependent on the previous key, instead of dependent on the parent.  The exact equation is:

PrivKey(i+1) = (ChainCode XOR Hash256(PubKey(i)) * PrivKey(i)
PubKey(i+1) = (ChainCode XOR Hash256(PubKey(i)) * PubKey(i)

Where * represents multiplication-mod-N (where N is the order of the secp256k1 group), and * represents scalar multiplication of an elliptic curve point.  Recall that PrivKey is a 32-byte integer, and PubKey is a (x,y) pair of 32-byte integers representing a point on the secp256k1 elliptic curve.

I do not remember why I chose [Chain XOR Hash(Pub)] instead of [Hash(Chain XOR Pub)].  The latter would've been preferable, but the one used is still sufficient.
1155  Bitcoin / Development & Technical Discussion / Re: Ultimate blockchain compression w/ trust-free lite nodes on: July 09, 2013, 07:00:18 PM
So this was "merged" with another topic... I'm not really sure what that means or why it happened.  But I'm not finding the most recent posts.   The last one I see is June 18.  Any idea what happened?  Any way to get all the posts since then?
1156  Bitcoin / Development & Technical Discussion / Re: Saving Transaction Outside of Network? on: July 09, 2013, 03:50:52 PM
I wouldn't say it's useless.  You could always create a transaction to someone (as Akka pointed out, it can be done with Armory), and then email it to them instead of broadcasting it.  Then it would be the same as writing a check from your bank checking account -- checks aren't guaranteed to have funds available to them, but if it's lost in the mail or the person moved (i.e. lost their wallet, etc), the coins never left your wallet.  

I had even thought about doing something like this in Armory as another kind of payment option.  

(1) Recipient gives the user his payment address.
(2) Sender, perhaps at a far later time doesn't know if that address is still valid, etc
(3) Sender creates a signed transaction and emails it to the recipient
(4) Recipient opens it in Armory and it says "This transaction sends 13.24 BTC to Wallet ABC" or "This transaction does not send coins to any wallet you own"
(5) Recipient presses "Broadcast" if they are happy with it.  Or replies with "this isn't valid, please use this address instead: ..."

It also makes MitM address swapping attack much less potent, because the person broadcasting is much more capable than the sender, of recognizing whether the transaction goes to their own wallet (edit: okay so this isn't actually true: because if the MitM can swap the addresses, he can probably also intercept the signed transaction and broadcast it himself... maybe only relevant if the tx is sent to the recipient through a different channel).  It also means that the recipient must actually act to broadcast the tx, which could be seen as actively acknowledging that payment was accepted.

This is interesting.   So as I understand it, a transaction can be created, however, unless it gets into the block chain, the funds aren't actually spent.   So this is one way to make a transaction reversible?

I wouldn't call it "reversible" since transactions don't really "happen" until it hits the network.  But yes it is more "flexible" than just broadcasting the transaction as-is.   Just like a check, no one should consider the transaction valid until it is submitted and "cleared."

The only problem with it is, it's very easy to accidentally invalidate this Bitcoin "check" because otherwise it would require locking coins in the wallet, usually an amount in excess of what the check is for (because you would have to lock the recipient amount and the change, which could be large and necessary for further transactions).  So I'm not sure how practical it is unless your wallet is low transaction volume and you expect them to be broadcast quickly.
1157  Bitcoin / Development & Technical Discussion / Re: SIGHASH_WITHINPUTVALUE: Super-lightweight HW wallets and offline data on: July 09, 2013, 03:43:58 PM
I have a ugly but backward compatible way to implement the OP idea:

1. Redefine one of the unassigned OP code (e.g. 0xfc) as OP_CHECKVALUE
2. When signing of input value is required, add an extra output like "<TxPrevHash> <TxPrevOutputIndex> <TxPrevOutputValue> OP_CHECKVALUE" is added, with 0 bitcoin assigned to this output
3. If an output of this format is found when validating a transaction, the engine will check whether the value of the specified output is same as TxPrevOutputValue. If not, the whole transaction is invalid. If yes, the code remove the top 3 stack items.
...
Any comments? At least I want to know if it works in theory

Does it have to be one extra output per input?  Couldn't you just have a single output specifying the fee for the whole tx?  It would essentially do the same thing, and the OP_NOP/OP_CHECKFEEVERIFY would still work with zero output value and be pruned. 

That would make it somewhat complicated to do more-advanced contracts though... where not all inputs and/or outputs are known at the time of signing (like the lighthouse contract).  Just more food for thought.
1158  Bitcoin / Development & Technical Discussion / Re: SIGHASH_WITHINPUTVALUE: Super-lightweight HW wallets and offline data on: July 09, 2013, 03:35:40 PM
I have a ugly but backward compatible way to implement the OP idea:

1. Redefine one of the unassigned OP code (e.g. 0xfc) as OP_CHECKVALUE
2. When signing of input value is required, add an extra output like "<TxPrevHash> <TxPrevOutputIndex> <TxPrevOutputValue> OP_CHECKVALUE" is added, with 0 bitcoin assigned to this output
3. If an output of this format is found when validating a transaction, the engine will check whether the value of the specified output is same as TxPrevOutputValue. If not, the whole transaction is invalid. If yes, the code remove the top 3 stack items.

More rules:
1. There could be multiple OP_CHECKVALUE in the same dummy output.
2. The whole transaction is invalid if the specified output is not found in the input list.

Advantage:
This is transparent to existing clients, making it a perfect soft-fork. For both old and new clients, the dummy output is provably unspendable and will be pruned from the UTXO set.

Disadvantage:
Bloats blockchain, and looks hacky

Any comments? At least I want to know if it works in theory

Does it have to be an extra output?  Couldn't we just put this in the TxIn script being signed directly?  Right now, a standard TxIn script is:

Code:
PUSH(Signature) PUSH(PubKey)

Couldn't we do:

Code:
PUSH(8bytefee) OP_CHECKFEEVERIFY PUSH(Signature) PUSH(PubKey)

EDIT: Never mind, I just realized that that those op-codes don't get signed, so they can be altered without breaking the signature.
1159  Bitcoin / Development & Technical Discussion / Re: A bitcoin blockchain parser in a few hundred lines of C++ on: July 08, 2013, 02:53:35 AM
Well, I'm not trying to write a full client, just something that can extract all of the transactions.

For that, as far as I can tell, I just need the two hash routines. In fact I think I'm getting pretty close to finishing this thing up.

Also, to be clear my coding website is largely educational. I'm writing this code to educate myself and releasing it open source to educate others.
Thanks,

John

Don't get caught up going down tangent paths.  Your issues with hashing sound much like someone who's never seen a logarithm before.  Reimplementing the log() function in C++ is not very useful nor educational, unless your goal is compiler optimizations or embedded software.  It's more important to understand the purpose and properties of the logarithm (hashing), than to distract those you are trying to educate with unnecessary details.  If I told you I didn't know what a logarithm but I needed it for my financial software, and I was working on implementing my own version of logarithm, you'd probably have the same reaction:  "go look up what a logarithm does and why it's important, and then just #include <cmath> and focus on which properties of it are needed by the financial software and why."   

Hashing is the one of the most fundamental and important atoms of cryptographic systems.  Especially Bitcoin.  And implementing it from scratch is not likely to give you any insight into how it works or how it fits into Bitcoin.   What you need to understand is that it's a function that takes any input, completely mangles it, and produces a seemingly-random X-byte output.  It must always produce the same answer for identical input, but change any bit should look equivalent to producing a random value.   It is intentionally non-invertible (i.e. SHA256 can take in any size string and always spits out 32 bytes), and each output bit should have no correlation with any input bit. 

In the context of Bitcoin transactions, it's goal is to produce a unique 32-byte identifier for a transaction, regardless of how many kB it is.  If any byte of the transaction is changed, the hash will look like a different 32-byte random number.  In the context of headers, this "randomness" to create a sort of lottery for miners.  Since we know the hash function should produce essentially-uniform randomness, we know that for a given difficulty and hashrate on the network, it should take approx 10 min on average for someone to find a lucky hash.

Similarly, if you go any further with this, you're going to need an ECDSA library in addition to hashing.  While elliptic curves are mathematically neat, you would be best to not reimplement it yourself unless you are working on speed-optimizing it.  If you think publickey->address was hard, try privatekey->publickey! (no, don't try it, just get a library and understand the properties of it).



1160  Bitcoin / Development & Technical Discussion / Re: A bitcoin blockchain parser in a few hundred lines of C++ on: July 07, 2013, 04:55:20 PM
Thanks, I prefer source too.

On further thought I have decided I'm going to retitle this post as a block-chain parser in a couple thousand lines of code; but it will still be just one CPP file when I'm done.

Actually it was kind of hard, it took me hours just to gather together the code to do SHA-256, RPMD-160, and base58cheked without dragging in massive libraries and dependencies.

I'm going to make a new Google code project called 'bitcoin-snippets' which will contain just the source to do each one of these specific operations.

Thanks,

John

Don't forget this is a crypto currency.  There is no way around having a general purpose crypto library available if you're going to do any coding in Bitcoin.  Just like you have standard headers in C++ for various data structures and algorithms, you are going to need these crypto algorithms available.   You're wasting your time reimplementing it, because it's all actually very simple, standard crypto operations (just combined in a creative way).  Once you have those standard operations available and you understand what they do, much of this will be much simpler.  Hashing is the bread and butter of Bitcoin, just get the libraries and do it.

And no one ever said bitcoin programming was easy, but you're taking the right size steps and you will get there with some patience.  What you are doing is exactly how I started two years ago and I think it's a fantastic way to learn.  You just have to appreciate that there's a lot to learn and you're going to spend a ton of time confused and digging for clarity.   That's part of the fun :-)

Pages: « 1 ... 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 [58] 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 ... 186 »
Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!