Skip to content

Commit

Permalink
Replace OP_EVAL (BIP 12) with Pay-to-script-hash (BIP 16).
Browse files Browse the repository at this point in the history
  • Loading branch information
gavinandresen committed Jan 13, 2012
1 parent d11a58a commit 922e8e2
Show file tree
Hide file tree
Showing 21 changed files with 824 additions and 544 deletions.
4 changes: 2 additions & 2 deletions src/base58.h
Expand Up @@ -255,7 +255,7 @@ class CBase58Data
// base58-encoded bitcoin addresses
// Public-key-hash-addresses have version 0 (or 192 testnet)
// The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key
// Script-hash-addresses (OP_EVAL) have version 5 (or 196 testnet)
// Script-hash-addresses have version 5 (or 196 testnet)
// The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script
class CBitcoinAddress : public CBase58Data
{
Expand Down Expand Up @@ -296,7 +296,7 @@ class CBitcoinAddress : public CBase58Data
fExpectTestNet = false;
break;
case SCRIPT_ADDRESS:
nExpectedSize = 20; // OP_EVAL, hash of CScript
nExpectedSize = 20; // Hash of CScript
fExpectTestNet = false;
break;

Expand Down
59 changes: 40 additions & 19 deletions src/bitcoinrpc.cpp
Expand Up @@ -1008,41 +1008,62 @@ Value addmultisigaddress(const Array& params, bool fHelp)
strAccount = AccountFromValue(params[2]);

// Gather public keys
if (keys.size() < nRequired)
if (nRequired < 1 || keys.size() < nRequired)
throw runtime_error(
strprintf("addmultisigaddress: wrong number of keys (got %d, need at least %d)", keys.size(), nRequired));
strprintf("wrong number of keys"
"(got %d, need at least %d)", keys.size(), nRequired));
std::vector<CKey> pubkeys;
pubkeys.resize(keys.size());
for (int i = 0; i < keys.size(); i++)
{
const std::string& ks = keys[i].get_str();
if (ks.size() == 130) // hex public key
pubkeys[i].SetPubKey(ParseHex(ks));
else if (ks.size() > 34) // base58-encoded
{
std::vector<unsigned char> vchPubKey;
if (DecodeBase58(ks, vchPubKey))
pubkeys[i].SetPubKey(vchPubKey);
else
throw runtime_error("Error base58 decoding key: "+ks);
}
else // bitcoin address for key in this wallet

// Case 1: bitcoin address and we have full public key:
CBitcoinAddress address(ks);
if (address.IsValid())
{
CBitcoinAddress address(ks);
if (address.IsScript())
throw runtime_error(
strprintf("%s is a pay-to-script address",ks.c_str()));
if (!pwalletMain->GetKey(address, pubkeys[i]))
throw runtime_error(
strprintf("addmultisigaddress: unknown address: %s",ks.c_str()));
strprintf("no full public key for address %s",ks.c_str()));
continue;
}

// Case 2: hex public key
if (IsHex(ks))
{
vector<unsigned char> vchPubKey = ParseHex(ks);
if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
throw runtime_error(" Invalid public key: "+ks);
// There is approximately a zero percent chance a random
// public key encoded as base58 will consist entirely
// of hex characters.
continue;
}
// Case 3: base58-encoded public key
{
vector<unsigned char> vchPubKey;
if (!DecodeBase58(ks, vchPubKey))
throw runtime_error("base58 decoding failed: "+ks);
if (vchPubKey.size() < 33) // 33 is size of a compressed public key
throw runtime_error("decoded public key too short: "+ks);
if (pubkeys[i].SetPubKey(vchPubKey))
continue;
}

throw runtime_error(" Invalid public key: "+ks);
}

// Construct using OP_EVAL
// Construct using pay-to-script-hash:
CScript inner;
inner.SetMultisig(nRequired, pubkeys);

uint160 scriptHash = Hash160(inner);
CScript scriptPubKey;
scriptPubKey.SetEval(inner);
pwalletMain->AddCScript(scriptHash, inner);
scriptPubKey.SetPayToScriptHash(inner);
pwalletMain->AddCScript(inner);
CBitcoinAddress address;
address.SetScriptHash160(scriptHash);

Expand Down Expand Up @@ -2681,7 +2702,7 @@ int CommandLineRPC(int argc, char *argv[])
string s = params[1].get_str();
Value v;
if (!read_string(s, v) || v.type() != array_type)
throw runtime_error("addmultisigaddress: type mismatch "+s);
throw runtime_error("type mismatch "+s);
params[1] = v.get_array();
}

Expand Down
2 changes: 1 addition & 1 deletion src/db.cpp
Expand Up @@ -942,7 +942,7 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
ssKey >> hash;
CScript script;
ssValue >> script;
if (!pwallet->LoadCScript(hash, script))
if (!pwallet->LoadCScript(script))
return DB_CORRUPT;
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/keystore.cpp
Expand Up @@ -36,10 +36,10 @@ bool CBasicKeyStore::AddKey(const CKey& key)
return true;
}

bool CBasicKeyStore::AddCScript(const uint160 &hash, const CScript& redeemScript)
bool CBasicKeyStore::AddCScript(const CScript& redeemScript)
{
CRITICAL_BLOCK(cs_KeyStore)
mapScripts[hash] = redeemScript;
mapScripts[Hash160(redeemScript)] = redeemScript;
return true;
}

Expand Down
4 changes: 2 additions & 2 deletions src/keystore.h
Expand Up @@ -25,7 +25,7 @@ class CKeyStore
virtual bool GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const;

// Support for BIP 0013 : see https://en.bitcoin.it/wiki/BIP_0013
virtual bool AddCScript(const uint160 &hash, const CScript& redeemScript) =0;
virtual bool AddCScript(const CScript& redeemScript) =0;
virtual bool HaveCScript(const uint160 &hash) const =0;
virtual bool GetCScript(const uint160 &hash, CScript& redeemScriptOut) const =0;

Expand Down Expand Up @@ -87,7 +87,7 @@ class CBasicKeyStore : public CKeyStore
}
return false;
}
virtual bool AddCScript(const uint160 &hash, const CScript& redeemScript);
virtual bool AddCScript(const CScript& redeemScript);
virtual bool HaveCScript(const uint160 &hash) const;
virtual bool GetCScript(const uint160 &hash, CScript& redeemScriptOut) const;
};
Expand Down

0 comments on commit 922e8e2

Please sign in to comment.