Bitcoin Forum
November 06, 2024, 05:00:58 AM *
News: Latest Bitcoin Core release: 28.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: what procedure to make hd descriptor multisig wallet, w/ bitcoin core 0.23 only  (Read 186 times)
CapLess2885 (OP)
Newbie
*
Offline Offline

Activity: 1
Merit: 1


View Profile
December 19, 2022, 10:13:46 AM
Last edit: December 23, 2022, 11:48:50 AM by CapLess2885
 #1

//////////////////////////////////////////////
nc50lc
Legendary
*
Online Online

Activity: 2590
Merit: 6332


Self-proclaimed Genius


View Profile
December 19, 2022, 01:11:04 PM
 #2

I am just curious about a clear detailled procedure for testing purposes, so please let us avoid warning posts or pro/con posts
I think the provided steps are detailed enough since there're even examples that you can use to your test.
The commands will also work in the GUI's console.

Now, for the creation process:
The problem is Bitcoin Core's GUI doesn't support the creation of such wallet natively so you'll have to find a way to safely create master private/public keys.
One way is to create temporary wallets, use "listdescriptors true" and copy any descriptor's "xprv key" (pick any).
Use listdescriptors false and copy the above's corresponding descriptor's "xpub key".
Then proceed to "In Bitcoin Core" steps of the linked tutorial, use those extended keys in step 3.

For the paper backup, just like above, Bitcoin Core doesn't support paper backup natively.
But since it's a descriptor wallet, you can write each cosigner's 'receiving' and 'change' descriptors which can be imported to new wallets when needed.
Follow step4-5 to import it to a new wallet, or backup the command in step 5 to have a ready-to-import (longer) string.

- are there things to be cautious after (like updating the backup of the descriptors...)?
Since all the child keys are based from the xprv key, you'll only need to backup once.

█▀▀▀











█▄▄▄
▀▀▀▀▀▀▀▀▀▀▀
e
▄▄▄▄▄▄▄▄▄▄▄
█████████████
████████████▄███
██▐███████▄█████▀
█████████▄████▀
███▐████▄███▀
████▐██████▀
█████▀█████
███████████▄
████████████▄
██▄█████▀█████▄
▄█████████▀█████▀
███████████▀██▀
████▀█████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
c.h.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀█











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
nc50lc
Legendary
*
Online Online

Activity: 2590
Merit: 6332


Self-proclaimed Genius


View Profile
December 20, 2022, 05:58:07 AM
 #3

1/ can I use sortedmulti instead of multi?
1.a/ if yes, then I do not need to care of the order of xprv/xpub, and I can just systematically do xprv/xpub, right?
Yes, that should work and will arrange the extended keys "lexicographically".
The example in the other thread uses "multi" instead of "sortedmulti" so the user can manually put his original wallet's arrangement of keys.

Quote from: CapLess2885
2/ in the other thread, you said "the derivation path differs per wallet, my example is based from BIP48". in my first try, I just copied the xprv/xpub and appended /0/* or /1/*, because when seeing your example, I thought you had voluntarily cut most of the derivation path and only let the /0/* part, but in fact it seems the full derivation path of your example is /0/*, right?  When I tried without the full derivation path, at the end during the verification process of receiving addresses I got different receiving addresses for each cosigner. Then I tried to do the same process with the full derivation path /84/0/0/0/*, and the verification process showed the same addresses for each cosigner.
Most of the path was cut because the extended keys to be imported are already at the "script type" level,
as shown in BIP48 (link), the derivation path looks like this: m/purpose'/coin_type'/account'/script_type'/change/address_index
Since his extended keys are at the script_type level, it should only be followed by /change/address_index  (check "In BIP39 tool" steps to see how he got the xprv/xpub keys)

You can provide the whole path if your xprv key is the master private key.

I don't know why you got different address when not using the whole path but it may be due to an error when constructing the descriptor.

Quote from: CapLess2885
3/ once they served their purpose, the first two temporary wallets can be then deleted and it is not requiered to be backed up right (as we have the xprv from the descriptors)?

4/ can you explain why any descriptor xprv type work?

5/ what does the sh mean in sh(wsh(multi? could wsh(multi work and how would it differ?

6/ I also tried sh(tr(multi but it does not work (higher level error if I recall)
3. Yes, after you created a backup of the cosigners' wallet.dat and the paper backups.

4. xprv keys are simply a private key appended with a chain code, there's nothing to tell if it's a 'master private key' or an 'extended private key'.
It's the descriptor that will tell your wallet which script type and derivation path to use.

5. sh is "Script Hash", wsh is "Witness Script Hash", it will work and will generate different address type which is P2WSH (bc1).
sh is used in the example since OP's original wallet is P2SH-SegWit (as I recalled in his other thread)

6. I think P2SH-Taproot will not be implemented based from what I've read; (can't find the reference though)
on the other hand, tr(multi isn't implemented.

█▀▀▀











█▄▄▄
▀▀▀▀▀▀▀▀▀▀▀
e
▄▄▄▄▄▄▄▄▄▄▄
█████████████
████████████▄███
██▐███████▄█████▀
█████████▄████▀
███▐████▄███▀
████▐██████▀
█████▀█████
███████████▄
████████████▄
██▄█████▀█████▄
▄█████████▀█████▀
███████████▀██▀
████▀█████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
c.h.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀█











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
nc50lc
Legendary
*
Online Online

Activity: 2590
Merit: 6332


Self-proclaimed Genius


View Profile
December 22, 2022, 06:29:42 AM
Last edit: December 22, 2022, 11:30:46 AM by nc50lc
 #4

listdescriptors true always show the master private key.
Therefore it means the key is at m/ level, so I should write everything after m.
Is this the logic?
listdesciptors true will show the private descriptors which has an xprv key but it's not indicated if it's the master private key or just an extended private key.
We should be able to tell based from the derivation path in the descriptor.
In my example, I'm using it as an extended private/public key.

I retried the process ten times with the full derivation path and each times the receiving addresses for each cosigners were the same.
I have retried  the process ten times without the full derivation path but only /0/* and each times the receiving addresses for each cosigners were different.
But viewing your answer, it seems it should not be.
So why that happen?
That's because of this (highlighted some parts):

Quote from: CapLess2885
22. switch to wallet1of2
23. importdescriptors "[{"desc":"wsh(sortedmulti(2,xprv1/84'/0'/0'/0/,xpub2/0/))#checksum1.0","timestamp":"now","active":true,"watching-only":false,"internal":false,"range":[0,999]}]"
24. importdescriptors "[{"desc":"wsh(sortedmulti(2,xprv1/84'/0'/0'/1/,xpub2/1/))#checksum1.1","timestamp":"now","active":true,"watching-only":false,"internal":true,"range":[0,999]}]"
25. switch to wallet2of2
26. importdescriptors "[{"desc":"wsh(sortedmulti(2,xprv2/84'/0'/0'/0/,xpub1/0/))#checksum2.0","timestamp":"now","active":true,"watching-only":false,"internal":false,"range":[0,999]}]"
nn. importdescriptors "[{"desc":"wsh(sortedmulti(2,xprv2/84'/0'/0'/1/,xpub1/1/))#checksum2.1","timestamp":"now","active":true,"watching-only":false,"internal":true,"range":[0,999]}]"
In wallet cosigner1, xprv1/xpub1 has a derivation path of m/84'/0'/0'/0/* while
In wallet cosigner2, xprv1/xpub1 has a derivation path of m/0/* which will produce different child keys.

The 'segwit sortedmulti' descriptors for those xprv/xpub key pairs should be,
For cosigner1 (receiving): wsh(sortedmulti(2,"xprv1"/0/*,"xpub2"/0/*)))
For cosigner1 (change):   wsh(sortedmulti(2,"xprv1"/1/*,"xpub2"/1/*)))
For cosigner2 (receiving): wsh(sortedmulti(2,"xprv2"/0/*,"xpub1"/0/*)))
For cosigner2 (change):   wsh(sortedmulti(2,"xprv2"/1/*,"xpub1"/1/*)))



But if you want to use the xprv as the master private key to use the full derivation path and the "cut-off" path for the xpub (extended public key),
you'll have to derive the master private key's "extended public key" at the correct level first before you can use the paths you've used in your descriptor.
I used iancoleman's BIP39 tool to get the extended keys in the example below.
(the master private key should pasted in "BIP32 Root Key" text box, then type custom derivation path, the extended keys will show below it)

For example (RegTest - BIP48):
Cosigner1:
Master Private key: tprv8ZgxMBicQKsPeVVYWjJqFVveMsJYUHC2Z2MxQ4sbd3FnfaQeCB3ACHFUbhkDojKF5LanxLtEbSA eBppqYR9DSYMmiX8ckuc6V84p79ZiBm3
Derive the extended public key at m/48'/0'/0'/2' (script level for native segwit)
Extended public key: tpubDF6UPFNY19vsBRAJ1XJ3GkatKf3NL8tQtJFfTqp8JXJe4v95A3pB2ppnxVproRB25uGzoJqSmkx ZCYEgLA1BEhRaTuvPFGQDrXbJYXZ5kv6
Cosigner2:
Master Private key: tprv8ZgxMBicQKsPej5sbayjwxAYerQAdBw6zeexWj3juLP2buD5YuEExRDVUNBkzdDQJU7hizofNBm k7Fxe7zUDF3kYAoqTfp6wNa9mFceD5mD
Derive the extended public key at m/48'/0'/0'/2' (script level for native segwit)
Extended public key: tpubDEwuZxw5ri4w8CErxS1Sk2nJmn7WBcZCz6yCK6M3tTWCYTK6G3sZpbMMSdhxpK8Pykfsv5W3xEQ GK2bqGEEqzCuMcYhvWMwoSJHB9kcQZLb

With that, you can now use your descriptor set-up:
Import to cosigner1:
Code:
importdescriptors "[{\"desc\": \"wsh(sortedmulti(2,tprv8ZgxMBicQKsPeVVYWjJqFVveMsJYUHC2Z2MxQ4sbd3FnfaQeCB3ACHFUbhkDojKF5LanxLtEbSAeBppqYR9DSYMmiX8ckuc6V84p79ZiBm3/48'/0'/0'/2'/0/*,tpubDEwuZxw5ri4w8CErxS1Sk2nJmn7WBcZCz6yCK6M3tTWCYTK6G3sZpbMMSdhxpK8Pykfsv5W3xEQGK2bqGEEqzCuMcYhvWMwoSJHB9kcQZLb/0/*))#e9sdw8sm\",\"timestamp\": \"now\",\"active\": true,\"watching-only\": false,\"internal\": false,\"range\": [0,999]}]"
Import to cosigner2:
Code:
importdescriptors "[{\"desc\": \"wsh(sortedmulti(2,tprv8ZgxMBicQKsPej5sbayjwxAYerQAdBw6zeexWj3juLP2buD5YuEExRDVUNBkzdDQJU7hizofNBmk7Fxe7zUDF3kYAoqTfp6wNa9mFceD5mD/48'/0'/0'/2'/0/*,tpubDF6UPFNY19vsBRAJ1XJ3GkatKf3NL8tQtJFfTqp8JXJe4v95A3pB2ppnxVproRB25uGzoJqSmkxZCYEgLA1BEhRaTuvPFGQDrXbJYXZ5kv6/0/*))#2gew492h\",\"timestamp\": \"now\",\"active\": true,\"watching-only\": false,\"internal\": false,\"range\": [0,999]}]"
(the path for the master prv key should be up to the "address_index" level: master_prv_key/48'/0'/0'/2'/0/*)
(the extended pub key is already at "script_type" level [the 2' above] so the path to "address_index" should only be: extended_pub_key/0/*)

Both wallets should generate the same address at first index: bcrt1qkhl5vjge39jv7c74frtq4pzxpa5jmguwz26vqatrm03uuhtjhtnq3dmftq

█▀▀▀











█▄▄▄
▀▀▀▀▀▀▀▀▀▀▀
e
▄▄▄▄▄▄▄▄▄▄▄
█████████████
████████████▄███
██▐███████▄█████▀
█████████▄████▀
███▐████▄███▀
████▐██████▀
█████▀█████
███████████▄
████████████▄
██▄█████▀█████▄
▄█████████▀█████▀
███████████▀██▀
████▀█████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
c.h.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀█











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
nc50lc
Legendary
*
Online Online

Activity: 2590
Merit: 6332


Self-proclaimed Genius


View Profile
December 22, 2022, 11:57:25 AM
 #5

Quote
listdesciptors true will show the private descriptors which has an xprv key but it's not indicated if it's the master private key or just an extended private key.
We should be able to tell based from the derivation path in the descriptor.
What made me say that listdescriptors always output the master private key is this post by andrew chow
Okay, that makes sense, thanks for the link.
I'll edit that part of my post accordingly.

That is what I do when it works, but without having to derive the extended public key. I just use the listdescriptors output (xpriv and xpub) and...
it works when I do "xprv1/84'/0'/0'/0/*,xpub2/0/*" and "xprv2/84'/0'/0'/0/*,xpub1/0/*", the receiving addresses are the same.
it does not work I do "xprv1/0/*, xpub2/0/*" and "xprv2/0/*, xpub1/0/*", the receiving addresses are different.
Theoretically, it shouldn't work since if xprv1/xpub1 are a pair and has different derivation paths in each descriptor,
the child keys would be different.

Example based from your description (Regtest):
Cosigner1 extended key pair:
Code:
tprv8iQSEqLHrnFCHx8W7sdSsLvmkdXSAohWJzetBKmptFWFERtJXezarLCvnPDQoDreyc1jcgwafmmcBhGvEqrfBzr9hBS5czdxMmq7DiAN3aq
tpubDF6UPFNY19vsBRAJ1XJ3GkatKf3NL8tQtJFfTqp8JXJe4v95A3pB2ppnxVproRB25uGzoJqSmkxZCYEgLA1BEhRaTuvPFGQDrXbJYXZ5kv6
Cosigner2 extended key pair:
Code:
tprv8iFsRYtqiLPGEjD54nLrLd8CCkba2HNJQoNR2aJkUBhohy4Kdf3ye6jVGXDHnUtgKYumyEWJgQ2Wgc3U6mjhwV16XVmbjiyG3pYaqxMsK6t
tpubDEwuZxw5ri4w8CErxS1Sk2nJmn7WBcZCz6yCK6M3tTWCYTK6G3sZpbMMSdhxpK8Pykfsv5W3xEQGK2bqGEEqzCuMcYhvWMwoSJHB9kcQZLb
Cosigner1 descriptor and importdescriptors command ("xprv1"/84'/0'/0'/0/*,"xpub2"/0/*):
Code:
importdescriptors "[{\"desc\": \"wsh(sortedmulti(2,tprv8iQSEqLHrnFCHx8W7sdSsLvmkdXSAohWJzetBKmptFWFERtJXezarLCvnPDQoDreyc1jcgwafmmcBhGvEqrfBzr9hBS5czdxMmq7DiAN3aq/84'/0'/0'/0/*,tpubDEwuZxw5ri4w8CErxS1Sk2nJmn7WBcZCz6yCK6M3tTWCYTK6G3sZpbMMSdhxpK8Pykfsv5W3xEQGK2bqGEEqzCuMcYhvWMwoSJHB9kcQZLb/0/*))#620d9yp0\",\"timestamp\": \"now\",\"active\": true,\"watching-only\": false,\"internal\": false,\"range\": [0,999]}]"
Cosigner2 descriptor and importdescriptors command ("xprv2"/84'/0'/0'/0/*,"xpub1"/0/*):
Code:
importdescriptors "[{\"desc\": \"wsh(sortedmulti(2,tprv8iFsRYtqiLPGEjD54nLrLd8CCkba2HNJQoNR2aJkUBhohy4Kdf3ye6jVGXDHnUtgKYumyEWJgQ2Wgc3U6mjhwV16XVmbjiyG3pYaqxMsK6t/84'/0'/0'/0/*,tpubDF6UPFNY19vsBRAJ1XJ3GkatKf3NL8tQtJFfTqp8JXJe4v95A3pB2ppnxVproRB25uGzoJqSmkxZCYEgLA1BEhRaTuvPFGQDrXbJYXZ5kv6/0/*))#ygmzfw0n\",\"timestamp\": \"now\",\"active\": true,\"watching-only\": false,\"internal\": false,\"range\": [0,999]}]"
Cosigner1's first address is: bcrt1qskd8r9gvp32lwxkw467fc4pe2mn6g58xgxvy0r0kkffct76ngffq6w5jlm
Cosigner2's first address is: bcrt1qyp3fd40qhdlvy0x8u7esurqqfhp8r7tthreye90puagtqwkgdcgqznkm65
I don't know how it worked at your end.


On the other hand, using "xprv1"/0/*,"xpub2"/0/* works, for example (Regtest):
Cosigner1 extended key pair:
Code:
tprv8iQSEqLHrnFCHx8W7sdSsLvmkdXSAohWJzetBKmptFWFERtJXezarLCvnPDQoDreyc1jcgwafmmcBhGvEqrfBzr9hBS5czdxMmq7DiAN3aq
tpubDF6UPFNY19vsBRAJ1XJ3GkatKf3NL8tQtJFfTqp8JXJe4v95A3pB2ppnxVproRB25uGzoJqSmkxZCYEgLA1BEhRaTuvPFGQDrXbJYXZ5kv6
Cosigner2 extended key pair:
Code:
tprv8iFsRYtqiLPGEjD54nLrLd8CCkba2HNJQoNR2aJkUBhohy4Kdf3ye6jVGXDHnUtgKYumyEWJgQ2Wgc3U6mjhwV16XVmbjiyG3pYaqxMsK6t
tpubDEwuZxw5ri4w8CErxS1Sk2nJmn7WBcZCz6yCK6M3tTWCYTK6G3sZpbMMSdhxpK8Pykfsv5W3xEQGK2bqGEEqzCuMcYhvWMwoSJHB9kcQZLb
Cosigner1 descriptor and importdescriptors command ("xprv1"/0/*,"xpub2"/0/*):
Code:
importdescriptors "[{\"desc\": \"wsh(sortedmulti(2,tprv8iQSEqLHrnFCHx8W7sdSsLvmkdXSAohWJzetBKmptFWFERtJXezarLCvnPDQoDreyc1jcgwafmmcBhGvEqrfBzr9hBS5czdxMmq7DiAN3aq/0/*,tpubDEwuZxw5ri4w8CErxS1Sk2nJmn7WBcZCz6yCK6M3tTWCYTK6G3sZpbMMSdhxpK8Pykfsv5W3xEQGK2bqGEEqzCuMcYhvWMwoSJHB9kcQZLb/0/*))#5269m2an\",\"timestamp\": \"now\",\"active\": true,\"watching-only\": false,\"internal\": false,\"range\": [0,999]}]"
Cosigner2 descriptor and importdescriptors command ("xprv2"/0/*,"xpub1"/0/*):
Code:
importdescriptors "[{\"desc\": \"wsh(sortedmulti(2,tprv8iFsRYtqiLPGEjD54nLrLd8CCkba2HNJQoNR2aJkUBhohy4Kdf3ye6jVGXDHnUtgKYumyEWJgQ2Wgc3U6mjhwV16XVmbjiyG3pYaqxMsK6t/0/*,tpubDF6UPFNY19vsBRAJ1XJ3GkatKf3NL8tQtJFfTqp8JXJe4v95A3pB2ppnxVproRB25uGzoJqSmkxZCYEgLA1BEhRaTuvPFGQDrXbJYXZ5kv6/0/*))#la8dlq5x\",\"timestamp\": \"now\",\"active\": true,\"watching-only\": false,\"internal\": false,\"range\": [0,999]}]"
Cosigner 1 and 2 wallets both derive bcrt1qkhl5vjge39jv7c74frtq4pzxpa5jmguwz26vqatrm03uuhtjhtnq3dmftq first address.

█▀▀▀











█▄▄▄
▀▀▀▀▀▀▀▀▀▀▀
e
▄▄▄▄▄▄▄▄▄▄▄
█████████████
████████████▄███
██▐███████▄█████▀
█████████▄████▀
███▐████▄███▀
████▐██████▀
█████▀█████
███████████▄
████████████▄
██▄█████▀█████▄
▄█████████▀█████▀
███████████▀██▀
████▀█████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
c.h.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀█











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
nc50lc
Legendary
*
Online Online

Activity: 2590
Merit: 6332


Self-proclaimed Genius


View Profile
December 22, 2022, 06:33:12 PM
 #6

Sorry, I think I found the issue and it's embarrassingly simple.

It works at your end because your xprv and xpub aren't a pair but actually the master private key and extended private key.
That's because listdescriptor true shows the master private key while listdescriptors shows the extended public key.
So using the full path for the xprv and the cut-off path for the xpub key works just like in my other example that's similar to yours.
The confusion is my fault for not testing the my suggested source of xprv and xpub keys.

My xprv and xpub keys on the other hand are pairs.

█▀▀▀











█▄▄▄
▀▀▀▀▀▀▀▀▀▀▀
e
▄▄▄▄▄▄▄▄▄▄▄
█████████████
████████████▄███
██▐███████▄█████▀
█████████▄████▀
███▐████▄███▀
████▐██████▀
█████▀█████
███████████▄
████████████▄
██▄█████▀█████▄
▄█████████▀█████▀
███████████▀██▀
████▀█████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
c.h.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀█











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
nc50lc
Legendary
*
Online Online

Activity: 2590
Merit: 6332


Self-proclaimed Genius


View Profile
December 23, 2022, 04:25:12 AM
 #7

so to conclude all of this... is there a better way between masterxprv/derivation + xpub/0 and xprv/0/*+xpub/0/* ?
are there any differences other than it is simpler to just use a simple xprv+xpub (no need to note the derivation path)?
Unfortunately, there's no other option in Bitcoin Core to make HD MultiSig setup other utilizing descriptors.
And descriptors require derivation path.

The other options createmultisig/addmultisig are for single multisig address.

There's currently also no way to generate MultiSig wallet using createwallet rpc, either.
Perhaps in future releases.

█▀▀▀











█▄▄▄
▀▀▀▀▀▀▀▀▀▀▀
e
▄▄▄▄▄▄▄▄▄▄▄
█████████████
████████████▄███
██▐███████▄█████▀
█████████▄████▀
███▐████▄███▀
████▐██████▀
█████▀█████
███████████▄
████████████▄
██▄█████▀█████▄
▄█████████▀█████▀
███████████▀██▀
████▀█████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
c.h.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀█











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
Pages: [1]
  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!