-
Notifications
You must be signed in to change notification settings - Fork 0
Pay to Contract
This example demonstrates how the certificate specification as well as bitcoind can handle a base key from which the customer can generate (i.e. derive) individual payment addresses for each transaction. We call this a pay-to-contract-payment.
As in Example 1 we have only one online-machine and assume to have changed to directory src.
We first get one fresh pubkey from our keystore:
@onlinemachine: ./bitcoind -testnet getnewaddress "p2cbase" true
02537af4f00677d5f13916618f865abcac79a51e485ad0da26aab2532f499af376
Note that getnewaddress has a (newly introduced) second argument. Setting it to true returns the pubkey instead of the address, which is what we need here. This pubkey is entered into foo1_p2csingle.yml
data:
version: 0.1
subjectname: Foo Inc.
contacts:
- type: EMAIL
value: [email protected]
- type: URL
value: "http://www.fooinc.com"
paymentkeys:
- algorithm:
type: P2CSINGLE
version: 0.1
value: [ 02537af4f00677d5f13916618f865abcac79a51e485ad0da26aab2532f499af376 ]Convert yaml to a binary protobuf message and print for verification:
@onlinemachine: bcert/mkbcrt.py foo1_p2csingle
This has produced the file foo1_p2csingle.bcrt which we can parse and pretty-print:
@onlinemachine: bcert/dumpbcrt.py foo1_p2csingle.bcrt
data {
version: "0.1"
subjectname: "Foo Inc."
contacts {
type: EMAIL
value: "[email protected]"
}
contacts {
type: URL
value: "http://www.fooinc.com"
}
paymentkeys {
usage: PAYMENT
algorithm {
type: P2CSINGLE
version: "0.1"
}
value: "\002Sz\364\360\006w\325\3619\026a\217\206Z\274\254y\245\036HZ\320\332&\252\262S/I\232\363v"
}
@onlinemachine: HEX=`xxd -p foo1_p2csingle.bcrt | tr -d "\n"`
or
@onlinemachine: HEX=`bcert/dumpbcrt.py -x foo1_p2csingle.bcrt`
Then
@onlinemachine: ./bitcoind -testnet bcsigncert foo1 $HEX
{
"bcsignresult" : {
"nFee" : 0.00050000,
"txid" : "862be784f1d1e1308a67b01c3c440310339c1a2cfb2ebb3b41a3ac0eb7e0e3af",
"fname" : "ecff20c2e787f20913522799cd8e216d4c69a355"
}
}
{
"nFee" : 0.00050000,
"txid" : "76d34af42d1b166ee81835d5066994930eee8785d119c3b82cd706501aa12e00",
"fname" : "418dbc6c2567baab3db74dbdb95bacc7f88e02e2"
}
@onlinemachine: bcert/dumpbcrt.py -s foo1
data {
version: "0.1"
subjectname: "Foo Inc."
contacts {
type: EMAIL
value: "[email protected]"
}
contacts {
type: URL
value: "http://www.fooinc.com"
}
paymentkeys {
usage: PAYMENT
algorithm {
type: P2CSINGLE
version: "0.1"
}
value: "\002Sz\364\360\006w\325\3619\026a\217\206Z\274\254y\245\036HZ\320\332&\252\262S/I\232\363v"
}
}
signatures {
algorithm {
type: BCPKI
version: "0.4"
}
value: "foo1"
}
Upload
@onlinemachine: HEX=`bcert/dumpbcrt.py -s -x foo1`
@onlinemachine: wget -O log.html http://btcrypt.org/cgi-bin/transfer.cgi?hexcert=$HEX
Download and import
@onlinemachine: wget -q --content-disposition -P ~/.bitcoin/testnet3/bcerts "http://btcrypt.org/cgi-bin/get.cgi?alias=foo1&format=b"
@onlinemachine: ./bitcoind -testnet bcverify foo1
{
"fSigned" : true,
"txid" : "862be784f1d1e1308a67b01c3c440310339c1a2cfb2ebb3b41a3ac0eb7e0e3af",
"confirmations" : 2,
"strTime" : "2013-02-07T13:40:37"
}
Now we are ready to pay directly to alias foo1 via the P2CSINGLE method (pay-to-contract with a single base key). For that we need a random number that we call the ticket. Either ticket was given to us by the payee or we can generate it ourselves and then submit it to the payee. It is passed to the RPC sendtoalias encoded as a big-endian hexadecimal number up to 256 bits. We come up with a 128 bit random number such as 1294bf2b3f8945d3b78cb55f6cf018a0 (generated by uuidgen).
@onlinemachine: ./bitcoind -testnet sendtoalias foo1 '[1,"1294bf2b3f8945d3b78cb55f6cf018a0"]' 0.5
{
"dest" : "n4YNcNUb8FfMrWbhe4C7iKS1ELNxCTgNmN",
"txid" : "1c849cef91405688b1f6ea7cdc2192c9a840b82e0263274477f2c07b4f87126d",
"vout" : 0
}
The number 1 in the second argument specified the payment method (1 means P2CSINGLE) and requires that foo1's certificate actually has a payment key for that method. The address listed under dest is the derived address. It is the address corresponding to the curve point ticket*G+P where G is the base point of the curve and P is the point stored in foo1's certificate. The output cannot be spent without knowledge of ticket, so sendtoalias has saved ticket in the wallet transaction (only partial output shown):
@onlinemachine: ./bitcoind -testnet gettransaction 1c849cef91405688b1f6ea7cdc2192c9a840b82e0263274477f2c07b4f87126d
{
[...]
"p2csingle" : "02537af4f00677d5f13916618f865abcac79a51e485ad0da26aab2532f499af376",
"ticket" : "1294bf2b3f8945d3b78cb55f6cf018a0",
"to" : "BCSIG_v0.4_F01<P2CSINGLE:1294bf2b3f8945d3b78cb55f6cf018a0> = n4YNcNUb8FfMrWbhe4C7iKS1ELNxCTgNmN",
[...]
"vout" : [
{ "value" : 0.50000000, "n" : 0,
"scriptPubKey" : { [...] "addresses" : [ " n4YNcNUb8FfMrWbhe4C7iKS1ELNxCTgNmN" ] } }
]
}
Before we can spend this output we have to import the private key corresponding to dest by giving both the basekey and ticket to the RPC importticket:
@onlinemachine: ./bitcoind -testnet getaddressesbyaccount p2cbase
[
"mpxXHdfkZGrWeLXtLAK3ci9kaqn2gREir1"
]
@onlinemachine: ./bitcoind -testnet importticket mpxXHdfkZGrWeLXtLAK3ci9kaqn2gREir1 1294bf2b3f8945d3b78cb55f6cf018a0
{
"derivedaddr" : "n4YNcNUb8FfMrWbhe4C7iKS1ELNxCTgNmN"
}
The return value convinces us that we imported the correct key. The RPC importticket has also derived a new account from the account name of the base key, which we set to p2cbase in the beginning.
@onlinemachine: ./bitcoind -testnet getaccount n4YNcNUb8FfMrWbhe4C7iKS1ELNxCTgNmN
p2cbase<1294bf2b3f8945d3b78cb55f6cf018a0>
Checking the balance:
@onlinemachine: ./bitcoind -testnet getbalance "p2cbase<1294bf2b3f8945d3b78cb55f6cf018a0>"
0.50000000
Re-spending the output:
@onlinemachine: ./bitcoind -testnet spendoutpoint 1c849cef91405688b1f6ea7cdc2192c9a840b82e0263274477f2c07b4f87126d 0
{
"nFee" : 0.00050000,
"txid" : "a02986a383cd912b931121d8dbf8554f9e15c88fc2ed5091996f7261f943a22b"
}
same as in First-Steps.
Next: Multi-Party Previous: First-Steps