- Take the raw transaction 0100000001a8e825e97723b40afbbc702d56b1f215b8e14d978357b55cdd754862b2bd2f5c01000000fdfd0000473044022001f4524959d67cbb94ec3b467701855994a28105190a116402996f82fdbf210b02205579e4a9fb3a79619aab36e839140907924afa9aedc56f0d0a4ffa91e16ae7150148304502210089d971e533932f4052c03c888525ba5d41f833a7e0ecef565e4106ef2dd4caff022060aa16868d08c85f7864b5be2b3f3d715b3aff15e36aeb47d48d7182684e2fae014c695221029c17ce9a40a71d21cf53844704dd611c85a2dc0072e22c9f14a485e6bb4ad4f42102b732df6d447e7fc04466522ebefe48fd07d9b5810ca1f572985f4386e36d5d132103e5c93bd1fbf87b30b093c2613b5c6ad7727005fd39fbee95136368c6918f13c053aeffffffff01905f01000000000017a9146e785c7efebeefbf201533ed5c8d07b6a524eadc8700000000
- Decode it with `decoderawtransaction` { ... "scriptSig" : { "asm" : "0 3044022001f4524959d67cbb94ec3b467701855994a28105190a116402996f82fdbf210b02205579e4a9fb3a79619aab36e839140907924afa9aedc56f0d0a4ffa91e16ae71501 304502210089d971e533932f4052c03c888525ba5d41f833a7e0ecef565e4106ef2dd4caff022060aa16868d08c85f7864b5be2b3f3d715b3aff15e36aeb47d48d7182684e2fae01 5221029c17ce9a40a71d21cf53844704dd611c85a2dc0072e22c9f14a485e6bb4ad4f42102b732df6d447e7fc04466522ebefe48fd07d9b5810ca1f572985f4386e36d5d132103e5c93bd1fbf87b30b093c2613b5c6ad7727005fd39fbee95136368c6918f13c053ae", "hex" : "00473044022001f4524959d67cbb94ec3b467701855994a28105190a116402996f82fdbf210b02205579e4a9fb3a79619aab36e839140907924afa9aedc56f0d0a4ffa91e16ae7150148304502210089d971e533932f4052c03c888525ba5d41f833a7e0ecef565e4106ef2dd4caff022060aa16868d08c85f7864b5be2b3f3d715b3aff15e36aeb47d48d7182684e2fae014c695221029c17ce9a40a71d21cf53844704dd611c85a2dc0072e22c9f14a485e6bb4ad4f42102b732df6d447e7fc04466522ebefe48fd07d9b5810ca1f572985f4386e36d5d132103e5c93bd1fbf87b30b093c2613b5c6ad7727005fd39fbee95136368c6918f13c053ae" }, ...
The last push is the p2sh redeem script. `decodescript` gives { "asm" : "2 029c17ce9a40a71d21cf53844704dd611c85a2dc0072e22c9f14a485e6bb4ad4f4 02b732df6d447e7fc04466522ebefe48fd07d9b5810ca1f572985f4386e36d5d13 03e5c93bd1fbf87b30b093c2613b5c6ad7727005fd39fbee95136368c6918f13c0 3 OP_CHECKMULTISIG", "reqSigs" : 2, "type" : "multisig", "addresses" : [ "13z5KYvFw3zTYLv3VutbEX1JZs9qCpzxBn", "1AM7HytoKfkx2GqGkxzJ5GLAaQPimyaC7A", "13FQsbdeZaN4uAUa4u9gsiF4qXX9Z3LbEk" ], "p2sh" : "3R1UQV2dHeXN2S3fiUqzFZnKougMdyEYv9" }
Notice that it's a different address than the one you are trying to spend `3FNa55HKt54bjfJMFssPFLX5KwJv39hsUj`. In your javascript, var utxo = { txId: escrowTxid, outputIndex: escrowTxVout, script: Script.buildMultisigOut(pubkeys, 2).toScriptHashOut(), satoshis: escrowAmount };
You form the redeem script from the pubkeys. With 3 public keys, there are 6 different permutations. Each of them leads to a different multi-sig address. Interestingly, none of them matches the one you need. - 123 3R1UQV2dHeXN2S3fiUqzFZnKougMdyEYv9 - 213 37yynZQMVYP2c7aU3MMQuRNT35Ef4n7gMA - 132 36Dpfp5JqZXnkRQE6QTCRPxUmsbp9iQVSR - 231 3DYmesQmQF5LrYG948bQfsuK7J9waZ9ZyG - 312 36zHiQfWSnWVeLXSY9qGqHTXqCLad1Qdyk - 321 3Lc3xpDc2TGgr4PukALsa4GMXvK69fA76h" Either you are trying to redeem from the wrong address, or you don't have the right pubkeys.
|
|
|
Great, thanks.
So, correct me if I've got this wrong: In a scenario where a signatory to a Multisig transaction can only see that transaction and they are expecting a specific number of signatories and a specific signing order they can verify the transaction is configured correctly before they sign. P2SH is not suitable for this scenario because the signatories and signing order is obfuscated by the hashing of the script. Furthermore for Multisig if you already know the signatories' private keys you can verify who the signatories are.
You mean public keys, don't you? These should be my last questions:
1. If redeemed successfully am I correct in assuming that the valid Scriptsigs will be written into the redeeming transaction's input? If so are the public keys included here as well as they are already in the previous transaction's outputs?
Only the signatures 2. I also take it a transaction with one or more Multisig inputs that has one or more Multisig outputs is standard? Assuming each output script is below 1,650 bytes and the total transaction is below 100,000 bytes.
Yes 3. I'm assuming there are no plans to discontinue Multisig as it is OP_CHECKMULTISIG which is used by other types of scripts, P2SH being one example.
I don't see why it would be removed 4. Can I also check: that the public key is stored in a full, usable format on the blockchain in transaction input? So is would for example usable in the above scenario i.e. you can see who the associated signatories are in the above situation if the public key has been used previously?
Yes you can. If a signature used a pub key, the node needed it to validate the tx. Therefore you can see it too.
|
|
|
Yes, in most cases the signature covers the entire new transaction (minus the signature itself and the pub scripts you are not signing). The exact process is complicated. It's worth knowing that the signer can choose to sign a portion of the transaction and therefore allow some changes to it.
|
|
|
The signatures used in multisig are produced the same way single signatures are created. Consequently, if someone modifies the transaction it invalidates any signature that was made on the original transaction.
Edit: The blockchain doesn't see the intermediate steps. It only sees the completed and signed transaction.
|
|
|
Yes to all your questions.
|
|
|
You may be over thinking this. First of all, P2SH and multi-sig are two orthogonal things. You can have a P2SH without multi-sig, a multi-sig without P2SH, etc.
So let's start with a non P2SH multi-sig. Since it's a normal tx, you have a pubscript and a sigscript. Put together, they should evaluate to true. A multi-sig pubscript looks like <M> <pubkey1> ... <pubkeyN>. Whoever funds the output decides what the public keys are and how many are needed. To spend it, M signatures must be provided in the redeem script.
This is all good but inconvenient because to add more money to the pool, i.e. to create another output that has the same spending requirements, you have to copy the multi-sig pubscript. Contrast this with the case of a pay-to-pubhash where the address is sufficient. From the address, the wallet app can calculate the pub hash and form the corresponding pay-to-pubhash script.
P2SH is the chosen solution to this issue (Other solutions were proposed). To generalize, we can consider a broader case where the script is more complicated. Basically, P2SH are not limited to multi-sig even though these are the most common usage.
Problem: We have a pubscript X. People should be able to send money with the same redeeming conditions without having X. The secrecy of X is not the main point, but having a super long 'address' that would decode to X is.
With P2SH, X is hashed like the pubkey is hashed for a classic pay-to-pubhash script. To differentiate from the later, another address version is used. That makes the P2SH addresses stand out because they start with '3' instead of '1'.
People can send money to the P2SH address without knowing X. Essentially, they are sending to the hash of X, i.e. the hash of the script. Hence, the name: Pay to Script Hash.
When someone wants to redeem the money, it gets a bit more complicated for him than in the normal case. He has to provide the redeem script (like in the normal case) *and* he has to provide X. First, the bitcoin node checks that the hash of X corresponds to the hash given in the P2SH. Then it further checks that the redeem script is correct in respect to X.
PS: A P2SH script looks like OP_HASH160 <hash> OP_EQUAL. The validation code recognizes this particular script and executes the two step validation. A client that is not aware of P2SH would only do the first step.
|
|
|
Thanks, I was wondering how one could tunnel a DNS request through the socks 5 proxy. It turns out, we can't.
|
|
|
When the core client runs through Tor and looks for seed nodes. Is DNS still used? And if so, does it go through the Tor proxy too?
|
|
|
When I run a regular node, my listening endpoint is part of the version msg and is relayed through addr messages. But when I run it as a Tor hidden service, is it advertised or people who want to connect must know my service onion address?
|
|
|
1. Not that I particularly endorse this method but you can go to bip32.org (or run it locally). There is an option for entering a passphrase manually.
Copy the resulting BIP32 extended key. It begins with xprv.
Open Electrum on your offline computer and choose File/New Restore/Restore a wallet. Paste the master private key. You can check the list of receiving addresses against the addresses on the website by choosing "Derivation path" m/0/i, and then 0, 1, etc. in key pair index.
Do the same on your online computer but with your master public key. It begins with xpub. You can get it by choosing 'Derivation Path' 'Info m' and picking the derived public key. Then again, check that the receiving addresses match with your offline computer.
2. Your online computer will show the balance across all your addresses without putting any fund at risk. your private keys are in cold storage.
|
|
|
The output you are getting "is the digest in binary form".
So just pass that to the function I gave you and you should see your hash in ASCII form.
(delete your fucking code and use what I gave you)
If you are just determined to be an idiot then no-one can help you (maybe give up on trying to write software).
Or maybe *you* should stop being condescending and at least provide good code. Your function has the same bug as his and then some. #include <sstream> #include <iomanip>
string print_hash( const string& hash ) { ostringstream outs;
if( hash.length == 32 ) { for( size_t i = 0; i < 32; i++ ) outs << hex << setw( 2 ) << setfill( '0' ) << ( unsigned )hash[ i ]; }
return outs.str( ); }
1. length is a method, not a field. It should be length() 2. you are missing the using clauses. At least 'using namespace std;' 3. not a bug per say but misleading name: 'print_hash' does not print the hash. It converts it to a hex string. 4. the reason why the output have sometimes ff is because of the (unsigned) cast. It casts the char to (unsigned int). Since there is no direct conversion path, it goes char -> int -> unsigned int. When the char is negative (because >= 0x80), the promotion to int preserves the negative sign. The proper way is to do in two steps (int)(unsigned char)hash[i]
Or in the OP's way printf("%02x", (unsigned char)myStringSHA[i]);
|
|
|
Replace return string((char*)abDigest);
With return string((char*)abDigest, 32);
String can store binary data.
|
|
|
- The missing characters are in the "control character" range (1-1F), they are not displayed but not replaced by # either. You don't need to cast char to bitset<8>. - The string constructor for a char* stop at the first null character because it takes a C-string. You can use string(char *, 32) or keep it as char *.
|
|
|
It is an impossible task to find 2048 completely different and easily memorable words
I beg to differ. Our vocabulary exceeds 10 000 words. Besides these words are not so memorable (at least for me) and I'm not sure they were meant to be. I think 8 million blocks is already "no limit", and it's likely to have a hardfork that will obsolete any current address scheme
It's quite big enough. But omitting the version bit simplifies the encoding. It is the only benefit but the cost is to strictly limit the use of such address and ignore many sophisticated use of the blockchain.
We have different use case in mind. Please refer to gmaxwell's criticism in the first page. Without covering the blockheight in the checksum, a miner could mine a "vanity address" without any cost. If the incentive is big enough (e.g. the address is "best adult adult adult web"), miners will fill the block with garbage and orphan other people's block in order to grab it.
An address points to a very specific location and one would have to be quite clever to produce a correct spot. Then he would have to mine the correct script and work with the miner to get the spot. I think he deserves that spot. Any addresses of this kind are meaningless without information from the blockchain. And the complexity added is completely transparent to end users. No one is expected to encode or decode it by hand.
From a coding point of view, having fewer dependencies is good. Eventually, people will vote for a BIP with their wallet ... app. It seems that we reach a point where we understand the pros/cons of each scheme. So I wish you good luck with your BIP and hope that it will be a big success.
|
|
|
Encode (blockheight, txIndex, txoIndex, pubScript) into a list of numbers between 0 and 2047. Preconditions: txoIndex < 4 The result is the concatenation of three sub lists that encodes each part ## blockHeight - The blockheight split into blocks of 10 bits, least significant block first. - All blocks except the last one has its most significant bit (11th bit) set to 1 ## txoIndex and checksum - The DSHA-256 is calculated over the pubScript - The first 2 bytes + 4 Least significant bits of the 3rd byte are kept, giving the 20-bit checksum - The txoIndex is appended - The 22 bit result is split into two groups of 11 bits ## txIndex - The txIndex is split into groups of 11 bits, least significant byte first # Transform the list into words Notes: - There is no version bit. The context should make the version clear. Alternatively, when the encoding needs to change, a different list of words can be substituted. - No limit on the blockheight - For the first 2^20 blocks and txIndex below 2^11, the scheme results in 5 words. It is independent from the actual number of transactions in the block - The encoding is essentially a combination of a variable length integer with continuation bit, a fixed record and a variable length integer. - The checksum only covers the pubscript. The goal of the method is to locate a particular address or more generally a particular pubscript. The blockHeight, txIndex and txoIndex provide the 'coordinates' of the pubscript and the checksum makes sure that it is the right one. If there is a block reorg, the decoding will retrieve a different pubscript and the verification will fail. - The encoding is a pure function. It only takes the location and the content of the data. No need for other information from the blockchain. - The result is not further encrypted. It is a public scheme. I'm a newb in Haskell so this is probably not idiomatic: import Debug.Trace import Data.Bits import Control.Applicative import Control.Monad import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as LB import qualified Crypto.Hash.SHA256 as SHA2 import qualified Data.Binary.Get as G
dsha = SHA2.hash . SHA2.hash setContinuationBit :: Int -> [Int] -> [Int] setContinuationBit position (x:xs) = (x .|. (shift 1 position)):xs
splitIntoWords :: Int -> [Int] -> Int -> Bool -> [Int] splitIntoWords 0 result size cont = reverse (if cont then (setContinuationBit size result) else result) splitIntoWords i result size cont = let mask = (shift 1 size)-1 in splitIntoWords (shift i (-size)) ((i .&. mask):result) size cont encodeTx :: Int -> Int -> Int -> B.ByteString -> [Int] encodeTx blockHeight txIndex txoIndex pubScript = let blockHeightEncoded = splitIntoWords blockHeight [] 10 True txoIndexEncoded = let shaDecoder = do bs <- (G.getByteString 4) shaChecksum <- liftM fromIntegral G.getWord32le return shaChecksum checksum = G.runGet shaDecoder (LB.fromChunks [dsha pubScript]) checksumAndTxoIndex = (shift checksum 2) .|. txoIndex checksumWords = splitIntoWords checksumAndTxoIndex [] 11 False in take 2 checksumWords txIndexEncoded = splitIntoWords txIndex [] 11 False in blockHeightEncoded ++ txoIndexEncoded ++ txIndexEncoded main = print (encodeTx 346694 500 2 (B.pack [1, 2, 40, 21]))
|
|
|
With checksum=20bits and blocks with =< 2048 txs, my proposal already guarantees a 5-word address for the first 4 outputs of any tx, same as hhanh00's. If your code gives you a 6-word address, there must be something wrong.
I can't see any reason not to allow people to encode the 5th output. With techniques like coinjoin, future transactions may have many outputs. Bitcoin is in its infancy and we won't know how people will use the blockchain in the future.
In my case, the txIndex <= 2048 guarantees 5 words regardless of the number of tx in the block. Could be the same for yours but I haven't checked. PS: You can try it out online at https://www.fpcomplete.com/user/hhanh00/adopted/txencoding
|
|
|
1. It could be that someone was testing the signature check count limit. The rules are a bit tricky and it could be a good place to look for a bug in an alternate implementation in order to cause a fork. Or he was just having fun.
2. OP_CHECKMULTISIG leaves OP_1 or OP_FALSE on the stack after evaluation. The OP_VERIFY pops that. Does that answer your question?
3. BIP-62 covers that. It will make using anything other than OP_0 an error. I think bitcoin core doesn't relay these tx but currently accepts them.
|
|
|
Without the ability to encode all outputs in the blockchain, the use of such mnemonic address is highly restricted. For example, people may want to use a mnemonic address to replace txid in daily use but the outputindex may not be <4. One particular useful case is for stealth address payment. The payer may use mnemonic address to help the payee to locate the output
If your BIP wants to cover every tx output, I agree with you. However, it was under my impression that the original proposal was about remembering an address that you previously set up. An implementation in F# let wordMask = (1L <<< 11) - 1L let rec splitIntoWords i result = match i with | 0L -> List.rev result | _ -> splitIntoWords (i >>> 11) ((i &&& wordMask) :: result)
let encodeTx (blockHeight: int64) (txIndex: int64) (txoIndex: int64) = assert(blockHeight < (1L <<< 31)) let blockHeightLSW = blockHeight &&& ((1L <<< 9) - 1L) let blockHeightWords = splitIntoWords (blockHeight >>> 9) [] let blockHeightEncoded = ((if blockHeight >= (1L <<< 20) then 1L else 0L) <<< 9 ||| blockHeightLSW) :: blockHeightWords
assert(txoIndex < 4L) let txoIndexEncoded = [txoIndex <<< 9; 0L]
let txIndexEncoded = splitIntoWords txIndex []
List.concat [blockHeightEncoded; txoIndexEncoded; txIndexEncoded]
|
|
|
|