def scenario( wallets, **kw ): global pk, pk2 testlib.blockstack_namespace_preorder( "test", wallets[1].addr, wallets[0].privkey ) testlib.next_block( **kw ) testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0], 10, 10, wallets[0].privkey, version_bits=blockstack.lib.config.NAMESPACE_VERSION_PAY_TO_CREATOR) testlib.next_block( **kw ) testlib.blockstack_namespace_ready( "test", wallets[1].privkey ) testlib.next_block( **kw ) # pay for a name in a v1 namespace with Stacks addr = virtualchain.address_reencode(virtualchain.get_privkey_address(pk)) addr2 = virtualchain.address_reencode(virtualchain.get_privkey_address(pk2)) # calculate the cost of doing so namespace = testlib.get_state_engine().get_namespace('test') stacks_price = blockstack.lib.scripts.price_name_stacks('foo', namespace, testlib.get_current_block(**kw)) btc_price = blockstack.lib.scripts.price_name('foo', namespace, testlib.get_current_block(**kw)) print '' print 'price of {} in Stacks is {}'.format('foo.test', stacks_price) print 'price of {} in BTC is {}'.format('foo.test', btc_price) print '' testlib.blockstack_send_tokens(addr, "STACKS", stacks_price + 2, wallets[0].privkey) testlib.blockstack_send_tokens(addr2, "STACKS", stacks_price + 1, wallets[0].privkey) testlib.send_funds(wallets[0].privkey, 3*btc_price, addr) testlib.send_funds(wallets[0].privkey, 3*btc_price, addr2) testlib.next_block(**kw) # preorder/register using Stacks testlib.blockstack_name_preorder( "foo.test", pk, addr2) testlib.blockstack_name_preorder( "bar.test", pk2, addr) testlib.next_block( **kw ) testlib.blockstack_name_register( "foo.test", pk, addr2 ) testlib.blockstack_name_register( "bar.test", pk2, addr ) testlib.next_block( **kw ) testlib.next_block( **kw ) testlib.next_block( **kw ) testlib.next_block( **kw ) # end of pay to namespace creator # renew using more stacks than we have (should fail) # bar.test should succeed testlib.blockstack_name_renew('foo.test', pk2, price={'units': 'STACKS', 'amount': stacks_price + 2}, expect_fail=True, safety_checks=False) testlib.blockstack_name_renew('bar.test', pk, price={'units': 'STACKS', 'amount': stacks_price + 1}) testlib.next_block(**kw) testlib.expect_snv_fail_at('foo.test', testlib.get_current_block(**kw))
def scenario(wallets, **kw): testlib.blockstack_namespace_preorder("test", wallets[1].addr, wallets[0].privkey) testlib.next_block(**kw) testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10, wallets[0].privkey) testlib.next_block(**kw) # derive importer keys and do imports # NOTE: breaks consensus trace from 0.14.0 private_keychain = keychain.PrivateKeychain.from_private_key( wallets[1].privkey) private_keys = [ wallets[1].privkey ] # NOTE: always start with the reveal key, then use children for i in xrange(0, 3): import_key = private_keychain.child(i).private_key() print "fund {} (child {})".format(import_key, i) res = testlib.send_funds( wallets[1].privkey, 100000000, virtualchain.BitcoinPrivateKey(import_key).public_key().address()) if 'error' in res: print json.dumps(res, indent=4, sort_keys=True) return False testlib.next_block(**kw) private_keys.append(import_key) resp = testlib.blockstack_name_import( "foo.test", addr_reencode("1BKufFedDrueBBFBXtiATB2PSdsBGZxf3N"), "11" * 20, wallets[1].privkey) # master if 'error' in resp: print json.dumps(resp, indent=4) testlib.next_block(**kw) resp = testlib.blockstack_name_import( "foo.test", addr_reencode("1ARVjrtKnUVWt2GNrpuFLnNCL2WGUhKdkW"), "33" * 20, private_keys[2]) # derived child 2 if 'error' in resp: print json.dumps(resp, indent=4) testlib.next_block(**kw) resp = testlib.blockstack_name_import( "foo.test", addr_reencode("1PYu4vKB3g2QLDFdurxqYSJ9aJSed7tne1"), "22" * 20, private_keys[1]) # derived child 1 if 'error' in resp: print json.dumps(resp, indent=4) testlib.next_block(**kw) testlib.blockstack_namespace_ready("test", wallets[1].privkey) testlib.next_block(**kw)
def do_POST(self): content_type = self.headers.getheader('content-type') postvars = {} if content_type is not None: ctype, pdict = cgi.parse_header(content_type) if ctype == 'multipart/form-data': postvars = cgi.parse_multipart(self.rfile, pdict) elif ctype == 'application/x-www-form-urlencoded': length = int(self.headers.getheader('content-length')) postvars = cgi.parse_qs(self.rfile.read(length), keep_blank_values=1) if self.path == '/sendfunds': # fund an address addr = postvars.get('addr', [None]) value = postvars.get('value', [None]) if addr[0] is None or value[0] is None: log.error("Missing addr or value") self.send_response(400, "Invalid request: missing addr or value") self.end_headers() return try: value = int(value[0]) addr = virtualchain.address_reencode(addr[0]) except: log.error("Failed to read addr and/or value") log.error("postvars = {}".format(postvars)) self.send_response(400, "Invalid addr or value") self.end_headers() return # can't take more than 0.1 BTC per address # send funds res = testlib.send_funds( testlib.get_default_payment_wallet().privkey, value, addr) if 'error' in res: log.error("Failed to send {} from {} to {}: {}".format( value, testlib.get_default_payment_wallet().privkey, addr, res)) self.send_response(400, "Failed to send value") self.end_headers() return self.send_response(302) self.send_header('location', '/') self.end_headers() return else: log.error("Unsupported path {}".format(self.path)) self.send_response(400, "Only support /sendfunds at this time") self.end_headers() return
def scenario( wallets, **kw ): global pk, pk2 testlib.blockstack_namespace_preorder( "test", wallets[1].addr, wallets[0].privkey ) testlib.next_block( **kw ) testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0], 10, 10, wallets[0].privkey ) testlib.next_block( **kw ) testlib.blockstack_namespace_ready( "test", wallets[1].privkey ) testlib.next_block( **kw ) # pay for a name in a v1 namespace with Stacks addr = virtualchain.address_reencode(virtualchain.get_privkey_address(pk)) addr2 = virtualchain.address_reencode(virtualchain.get_privkey_address(pk2)) # calculate the cost of doing so namespace = testlib.get_state_engine().get_namespace('test') stacks_price = blockstack.lib.scripts.price_name_stacks('foo', namespace, testlib.get_current_block(**kw)) btc_price = blockstack.lib.scripts.price_name('foo', namespace, testlib.get_current_block(**kw)) print '' print 'price of {} in Stacks is {}'.format('foo.test', stacks_price) print 'price of {} in BTC is {}'.format('foo.test', btc_price) print '' testlib.blockstack_send_tokens(addr, "STACKS", stacks_price + 1, wallets[0].privkey) testlib.blockstack_send_tokens(addr2, "STACKS", stacks_price + 1, wallets[0].privkey) testlib.send_funds(wallets[0].privkey, 2*btc_price, addr) testlib.send_funds(wallets[0].privkey, 2*btc_price, addr2) testlib.next_block(**kw) # preorder/register using Stacks testlib.blockstack_name_preorder( "foo.test", pk, addr2, price={'units': 'STACKS', 'amount': stacks_price + 1}) testlib.next_block( **kw ) testlib.blockstack_name_register( "foo.test", pk, addr2 ) testlib.next_block( **kw ) # renew using Stacks testlib.blockstack_name_renew('foo.test', pk2, price={'units': 'STACKS', 'amount': stacks_price + 1}) testlib.next_block(**kw)
def scenario( wallets, **kw ): # try to spend tokens to ourselves testlib.blockstack_send_tokens(wallets[0].addr, "STACKS", 100000, wallets[0].privkey, safety_checks=False, expect_fail=True) testlib.next_block(**kw) # end of 689 assert virtualchain.lib.indexer.StateEngine.get_block_statistics(testlib.get_current_block(**kw))['num_processed_ops'] == 0 # try to spend more tokens than we have testlib.blockstack_send_tokens(wallets[1].addr, "STACKS", 600001, wallets[0].privkey, safety_checks=False, expect_fail=True) testlib.next_block(**kw) assert virtualchain.lib.indexer.StateEngine.get_block_statistics(testlib.get_current_block(**kw))['num_processed_ops'] == 0 # try to spend tokens that don't exist testlib.blockstack_send_tokens(wallets[1].addr, "noop", 600000, wallets[0].privkey, safety_checks=False, expect_fail=True) testlib.next_block(**kw) assert virtualchain.lib.indexer.StateEngine.get_block_statistics(testlib.get_current_block(**kw))['num_processed_ops'] == 0 # try to spend tokens with an invalid consensus hash (note that this is epoch 4) testlib.blockstack_send_tokens(wallets[1].addr, "STACKS", 600000, wallets[0].privkey, consensus_hash='00' * 16, safety_checks=False, expect_fail=True) testlib.next_block(**kw) assert virtualchain.lib.indexer.StateEngine.get_block_statistics(testlib.get_current_block(**kw))['num_processed_ops'] == 0 # try to spend tokens from an account that doesn't exist pk = virtualchain.lib.ecdsalib.ecdsa_private_key().to_hex() addr = virtualchain.address_reencode(virtualchain.get_privkey_address(pk)) testlib.send_funds(wallets[0].privkey, 10240000, addr) testlib.blockstack_send_tokens(wallets[1].addr, "STACKS", 100000, pk, safety_checks=False, expect_fail=True) testlib.next_block(**kw) assert virtualchain.lib.indexer.StateEngine.get_block_statistics(testlib.get_current_block(**kw))['num_processed_ops'] == 0 # try to send 0 tokens testlib.blockstack_send_tokens(wallets[1].addr, "STACKS", 0, wallets[0].privkey, safety_checks=False, expect_fail=True) testlib.next_block(**kw) assert virtualchain.lib.indexer.StateEngine.get_block_statistics(testlib.get_current_block(**kw))['num_processed_ops'] == 0
def scenario( wallets, **kw ): global pk testlib.blockstack_namespace_preorder( "test", wallets[1].addr, wallets[0].privkey ) testlib.next_block( **kw ) testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0], 10, 10, wallets[0].privkey ) testlib.next_block( **kw ) testlib.blockstack_namespace_ready( "test", wallets[1].privkey ) testlib.next_block( **kw ) # pay for a name in a v1 namespace with Stacks addr = virtualchain.address_reencode(virtualchain.get_privkey_address(pk)) # calculate the cost of doing so namespace = testlib.get_state_engine().get_namespace('test') stacks_price = blockstack.lib.scripts.price_name_stacks('foo', namespace, testlib.get_current_block(**kw)) btc_price = blockstack.lib.scripts.price_name('foo', namespace, testlib.get_current_block(**kw)) print '' print 'price of {} in Stacks is {}'.format('foo.test', stacks_price) print '' testlib.blockstack_send_tokens(addr, "STACKS", stacks_price + 1, wallets[0].privkey) testlib.send_funds(wallets[0].privkey, btc_price - 5500 - 1, addr) # deliberately insufficient funds for ordering the name in BTC testlib.next_block(**kw) # preorder/register using Stacks, but overpay testlib.blockstack_name_preorder( "foo.test", pk, wallets[3].addr, price={'units': 'STACKS', 'amount': stacks_price + 2}, expect_fail=True, safety_checks=False) testlib.next_block( **kw ) testlib.expect_snv_fail_at('foo.test', testlib.get_current_block(**kw)) testlib.send_funds(wallets[0].privkey, btc_price - 5500 - 1, addr) # deliberately insufficient funds for ordering the name in BTC testlib.blockstack_name_register( "foo.test", pk, wallets[3].addr ) # should fail testlib.next_block( **kw ) testlib.expect_snv_fail_at('foo.test', testlib.get_current_block(**kw))
def scenario( wallets, **kw ): testlib.blockstack_namespace_preorder( "test", wallets[1].addr, wallets[0].privkey ) testlib.next_block( **kw ) testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0], 10, 10, wallets[0].privkey ) testlib.next_block( **kw ) # derive importer keys and do imports # NOTE: breaks consensus trace from 0.14.0 private_keychain = keychain.PrivateKeychain.from_private_key( wallets[1].privkey ) private_keys = [wallets[1].privkey] # NOTE: always start with the reveal key, then use children for i in xrange(0, 3): import_key = private_keychain.child(i).private_key() print "fund {} (child {})".format(import_key, i) res = testlib.send_funds( wallets[1].privkey, 100000000, virtualchain.BitcoinPrivateKey(import_key).public_key().address() ) if 'error' in res: print json.dumps(res, indent=4, sort_keys=True) return False testlib.next_block(**kw) private_keys.append(import_key) resp = testlib.blockstack_name_import( "foo.test", addr_reencode("1BKufFedDrueBBFBXtiATB2PSdsBGZxf3N"), "11" * 20, wallets[1].privkey ) # master if 'error' in resp: print json.dumps(resp, indent=4 ) testlib.next_block( **kw ) resp = testlib.blockstack_name_import( "foo.test", addr_reencode("1ARVjrtKnUVWt2GNrpuFLnNCL2WGUhKdkW"), "33" * 20, private_keys[2] ) # derived child 2 if 'error' in resp: print json.dumps(resp, indent=4 ) testlib.next_block( **kw ) resp = testlib.blockstack_name_import( "foo.test", addr_reencode("1PYu4vKB3g2QLDFdurxqYSJ9aJSed7tne1"), "22" * 20, private_keys[1] ) # derived child 1 if 'error' in resp: print json.dumps(resp, indent=4 ) testlib.next_block( **kw ) testlib.blockstack_namespace_ready( "test", wallets[1].privkey ) testlib.next_block( **kw )
def scenario(wallets, **kw): # pass 100 stacks around in a circle. new_keys = [wallets[0].privkey] + [ virtualchain.lib.ecdsalib.ecdsa_private_key().to_hex() for i in range(0, 4) ] for k in range(0, 4): for j in range(0, len(new_keys)): i = j new_addr = virtualchain.get_privkey_address( new_keys[(i + 1) % len(new_keys)]) cur_addr = virtualchain.get_privkey_address( new_keys[i % len(new_keys)]) initial_new_balance_info = json.loads( testlib.nodejs_cli('balance', new_addr)) initial_cur_balance_info = json.loads( testlib.nodejs_cli('balance', cur_addr)) print '\n initial new balance info: {} \n'.format( initial_new_balance_info) if 'STACKS' not in initial_new_balance_info: initial_new_balance_info['STACKS'] = 0 if i > 0: testlib.send_funds(wallets[0].privkey, 500000, cur_addr) testlib.send_funds(wallets[0].privkey, 500000, new_addr) testlib.blockstack_send_tokens(new_addr, 'STACKS', 100, new_keys[i % len(new_keys)], safety_checks=False) # consolidate utxos = testlib.get_utxos(wallets[0].addr) if len(utxos) > 1: balance = testlib.get_balance(wallets[0].addr) testlib.send_funds(wallets[0].privkey, balance - 5500, wallets[0].addr, change=False) utxos = testlib.get_utxos(new_addr) if len(utxos) > 1: balance = testlib.get_balance(new_addr) testlib.send_funds(new_keys[(i + 1) % len(new_keys)], balance - 5500, new_addr, change=False) testlib.next_block(**kw) for j in range(0, len(new_keys)): i = j new_addr = virtualchain.get_privkey_address( new_keys[(i + 1) % len(new_keys)]) cur_addr = virtualchain.get_privkey_address( new_keys[i % len(new_keys)]) if j == len(new_keys) - 1: if (i + 1) % len(new_keys) != 0: # last address should have 100 stacks, unless new_addr is wallets[0] balance_info = json.loads( testlib.nodejs_cli('balance', new_addr)) assert int(balance_info['STACKS']) == 100 else: if i % len(new_keys) != 0: # every other address, except wallets[0], should have 0 balance balance_info = json.loads( testlib.nodejs_cli('balance', cur_addr)) assert int(balance_info['STACKS']) == 0 # consolidate for j in range(0, len(new_keys)): cur_addr = virtualchain.get_privkey_address( new_keys[i % len(new_keys)]) utxos = testlib.get_utxos(cur_addr) if len(utxos) > 1: balance = testlib.get_balance(cur_addr) testlib.send_funds(new_keys[i % len(new_keys)], balance - 5500, cur_addr, change=False) testlib.next_block(**kw) # each *new* address has 4 history items -- four spends, four receives for new_key in new_keys[1:]: new_addr = virtualchain.get_privkey_address(new_key) history = requests.get( 'http://localhost:16268/v1/accounts/{}/history?page=0'.format( new_addr)).json() # should have gotten 4 debits for 100, and 4 credits for 100 assert int(history[0]['credit_value']) == 400, history assert int(history[0]['debit_value']) == 400, history assert len(history) == 8, history
def scenario( wallets, **kw ): global pk, pk2 testlib.blockstack_namespace_preorder( "test", wallets[1].addr, wallets[0].privkey ) testlib.next_block( **kw ) testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6,6,6,6,6,6,0,0,0,0,0,0,0,0,0,0], 10, 10, wallets[0].privkey, version_bits=blockstack.lib.config.NAMESPACE_VERSION_PAY_TO_CREATOR) testlib.next_block( **kw ) testlib.blockstack_namespace_ready( "test", wallets[1].privkey ) testlib.next_block( **kw ) # pay for a name in a v1 namespace with Stacks addr = virtualchain.address_reencode(virtualchain.get_privkey_address(pk)) addr2 = virtualchain.address_reencode(virtualchain.get_privkey_address(pk2)) # calculate the cost of doing so namespace = testlib.get_state_engine().get_namespace('test') stacks_price = blockstack.lib.scripts.price_name_stacks('foo', namespace, testlib.get_current_block(**kw)) btc_price = blockstack.lib.scripts.price_name('foo', namespace, testlib.get_current_block(**kw)) print '' print 'price of {} in Stacks is {}'.format('foo.test', stacks_price) print 'price of {} in BTC is {}'.format('foo.test', btc_price) print '' testlib.blockstack_send_tokens(addr, "STACKS", 8*stacks_price, wallets[0].privkey) testlib.blockstack_send_tokens(addr2, "STACKS", 8*stacks_price, wallets[0].privkey) testlib.send_funds(wallets[0].privkey, 8*btc_price, addr) testlib.send_funds(wallets[0].privkey, 8*btc_price, addr2) testlib.next_block(**kw) def _tx_pay_btc(txhex, privk, burn_price, burn_addr=blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS): tx = virtualchain.btc_tx_deserialize(txhex) # up the burn amount tx['outs'][3]['script'] = virtualchain.btc_make_payment_script(burn_addr) tx['outs'][3]['value'] = burn_price tx['outs'][4]['value'] -= burn_price # re-sign for i in tx['ins']: i['script'] = '' txhex = virtualchain.btc_tx_serialize(tx) _addr = virtualchain.address_reencode(virtualchain.get_privkey_address(privk)) txhex_signed = virtualchain.tx_sign_all_unsigned_inputs(privk, testlib.get_utxos(_addr), txhex) # re-sign the last output with the payment key tx_signed = virtualchain.btc_tx_deserialize(txhex_signed) tx_signed['ins'][-1]['script'] = '' txhex_signed = virtualchain.tx_sign_all_unsigned_inputs(testlib.get_default_payment_wallet().privkey, testlib.get_utxos(testlib.get_default_payment_wallet().addr), virtualchain.btc_tx_serialize(tx_signed)) print txhex_signed res = testlib.broadcast_transaction(txhex_signed) assert 'error' not in res return res # preorder/register using BTC testlib.blockstack_name_preorder( "foo.test", pk, addr2 ) testlib.blockstack_name_preorder( "bar.test", pk, addr2 ) testlib.blockstack_name_preorder( "baz.test", pk, addr2 ) testlib.blockstack_name_preorder( "goo.test", pk, addr2 ) testlib.next_block( **kw ) testlib.blockstack_name_register( "foo.test", pk, addr2 ) testlib.blockstack_name_register( "bar.test", pk, addr2 ) testlib.blockstack_name_register( "baz.test", pk, addr2 ) testlib.blockstack_name_register( "goo.test", pk, addr2 ) testlib.next_block( **kw ) # try to renew using Stacks (won't work, since we used the wrong burn address while pay-to-creator was active) res = testlib.blockstack_name_renew('foo.test', pk2, price={'units': 'STACKS', 'amount': stacks_price}, burn_addr=blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS, safety_checks=False, expect_fail=True, tx_only=True) res = _tx_pay_btc(res['transaction'], pk2, btc_price) # try to renew using Stacks (won't work, since we send tokens to the wrong burn address for tokens) res = testlib.blockstack_name_renew('bar.test', pk2, price={'units': 'STACKS', 'amount': stacks_price}, burn_addr=wallets[0].addr, safety_checks=False, expect_fail=True, tx_only=True) res = _tx_pay_btc(res['transaction'], pk2, btc_price, wallets[0].addr) # try to renew using Stacks (won't work, since we used the wrong burn address while pay-to-creator was active). Also underpay BTC res = testlib.blockstack_name_renew('baz.test', pk2, price={'units': 'STACKS', 'amount': stacks_price}, burn_addr=blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS, safety_checks=False, expect_fail=True, tx_only=True) res = _tx_pay_btc(res['transaction'], pk2, btc_price - 1) # try to renew using Stacks (won't work, since we send tokens to the wrong burn address for tokens). Also underpay BTC res = testlib.blockstack_name_renew('goo.test', pk2, price={'units': 'STACKS', 'amount': stacks_price}, burn_addr=wallets[0].addr, safety_checks=False, expect_fail=True, tx_only=True) res = _tx_pay_btc(res['transaction'], pk2, btc_price - 1, wallets[0].addr) testlib.next_block(**kw) # all should have failed assert virtualchain.lib.indexer.StateEngine.get_block_statistics(testlib.get_current_block(**kw))['num_processed_ops'] == 0 # try to renew using Stacks (won't work, since we're still collecting fees in BTC and need to send to the namespace creator's address) res = testlib.blockstack_name_renew('foo.test', pk2, price={'units': 'STACKS', 'amount': stacks_price-1}, burn_addr=blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS, safety_checks=False, expect_fail=True, tx_only=True) res = _tx_pay_btc(res['transaction'], pk2, btc_price) res = testlib.blockstack_name_renew('bar.test', pk2, price={'units': 'STACKS', 'amount': stacks_price-1}, burn_addr=wallets[0].addr, safety_checks=False, expect_fail=True, tx_only=True) res = _tx_pay_btc(res['transaction'], pk2, btc_price, wallets[0].addr) # try to renew using Stacks (won't work, since we used the wrong burn address while pay-to-creator was active). Also underpay BTC res = testlib.blockstack_name_renew('baz.test', pk2, price={'units': 'STACKS', 'amount': stacks_price-1}, burn_addr=blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS, safety_checks=False, expect_fail=True, tx_only=True) res = _tx_pay_btc(res['transaction'], pk2, btc_price - 1) # try to renew using Stacks (won't work, since we send tokens to the wrong burn address for tokens). Also underpay BTC res = testlib.blockstack_name_renew('goo.test', pk2, price={'units': 'STACKS', 'amount': stacks_price-1}, burn_addr=wallets[0].addr, safety_checks=False, expect_fail=True, tx_only=True) res = _tx_pay_btc(res['transaction'], pk2, btc_price - 1, wallets[0].addr) testlib.next_block(**kw) # all should have failed assert virtualchain.lib.indexer.StateEngine.get_block_statistics(testlib.get_current_block(**kw))['num_processed_ops'] == 0 # try to renew using Stacks, now that pay-to-creator has expired res = testlib.blockstack_name_renew('foo.test', pk2, price={'units': 'STACKS', 'amount': stacks_price}, expect_success=True, tx_only=True) res = _tx_pay_btc(res['transaction'], pk2, btc_price) # should fail--can't mix stacks and btc res = testlib.blockstack_name_renew('bar.test', pk2, price={'units': 'STACKS', 'amount': stacks_price-1}, expect_fail=True, tx_only=True) res = _tx_pay_btc(res['transaction'], pk2, btc_price) # should succeed--paid in stacks res = testlib.blockstack_name_renew('baz.test', pk2, price={'units': 'STACKS', 'amount': stacks_price}, expect_success=True, tx_only=True) res = _tx_pay_btc(res['transaction'], pk2, btc_price - 1) # should fail--wrong burn address res = testlib.blockstack_name_renew('goo.test', pk2, price={'units': 'STACKS', 'amount': stacks_price}, burn_addr=wallets[0].addr, safety_checks=False, expect_fail=True, tx_only=True) res = _tx_pay_btc(res['transaction'], pk2, btc_price, wallets[0].addr) testlib.next_block(**kw) # only two should have succeeded assert virtualchain.lib.indexer.StateEngine.get_block_statistics(testlib.get_current_block(**kw))['num_processed_ops'] == 2
def scenario(wallets, **kw): global pk testlib.blockstack_namespace_preorder("test1", wallets[1].addr, wallets[0].privkey) testlib.blockstack_namespace_preorder("test2", wallets[1].addr, wallets[0].privkey) testlib.blockstack_namespace_preorder("test3", wallets[1].addr, wallets[0].privkey) testlib.next_block(**kw) testlib.blockstack_namespace_reveal( "test1", wallets[1].addr, 52595, 250, 4, [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10, wallets[0].privkey, version_bits=1) testlib.blockstack_namespace_reveal( "test2", wallets[1].addr, 52595, 250, 4, [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10, wallets[0].privkey, version_bits=2) testlib.blockstack_namespace_reveal( "test3", wallets[1].addr, 52595, 250, 4, [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10, wallets[0].privkey, version_bits=3) testlib.next_block(**kw) testlib.blockstack_namespace_ready("test1", wallets[1].privkey) testlib.blockstack_namespace_ready("test2", wallets[1].privkey) testlib.blockstack_namespace_ready("test3", wallets[1].privkey) testlib.next_block(**kw) # pay for a name in a v1 namespace with Stacks addr = virtualchain.address_reencode(virtualchain.get_privkey_address(pk)) # calculate the cost of doing so namespace = testlib.get_state_engine().get_namespace('test1') stacks_price = blockstack.lib.scripts.price_name_stacks( 'foo', namespace, testlib.get_current_block(**kw)) btc_price = blockstack.lib.scripts.price_name( 'foo', namespace, testlib.get_current_block(**kw)) print '' print 'price of {} in Stacks is {}'.format('foo.test', stacks_price) print '' testlib.blockstack_send_tokens(addr, "STACKS", 3 * stacks_price, wallets[0].privkey) testlib.send_funds( wallets[0].privkey, btc_price - 5500 - 1, addr) # deliberately insufficient funds for ordering the name in BTC testlib.next_block(**kw) wallet_before_burn = testlib.get_balance(wallets[0].addr) # preorder/register in all three namespaces testlib.blockstack_name_preorder("foo.test1", pk, wallets[3].addr, price={ 'units': 'STACKS', 'amount': stacks_price }) testlib.blockstack_name_preorder("bar.test1", wallets[1].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo.test2", wallets[1].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo.test3", wallets[1].privkey, wallets[3].addr) testlib.next_block(**kw) wallet_after_burn = testlib.get_balance(wallets[0].addr) if wallet_after_burn - wallet_before_burn != btc_price: print 'foo.test2 did not pay {} to {} (but paid {})'.format( btc_price, wallets[0].addr, wallet_after_burn - wallet_before_burn) return False testlib.send_funds( wallets[0].privkey, btc_price - 5500 - 1, addr) # deliberately insufficient funds for ordering the name in BTC testlib.blockstack_name_register("foo.test1", pk, wallets[3].addr) # paid in Stacks testlib.blockstack_name_register("bar.test1", wallets[1].privkey, wallets[3].addr) # paid in BTC testlib.blockstack_name_register( "foo.test2", wallets[1].privkey, wallets[3].addr) # paid in BTC to wallets[0] testlib.blockstack_name_register("foo.test3", wallets[1].privkey, wallets[3].addr) # paid in Stacks testlib.next_block(**kw) testlib.send_funds( wallets[0].privkey, btc_price - 5500 - 1, addr) # deliberately insufficient funds for ordering the name in BTC wallet_before_burn = testlib.get_balance(wallets[0].addr) testlib.blockstack_name_renew("foo.test1", wallets[3].privkey, price={ 'units': 'STACKS', 'amount': stacks_price }) # paid in Stacks testlib.blockstack_name_renew("bar.test1", wallets[3].privkey) # paid in BTC testlib.blockstack_name_renew( "foo.test2", wallets[3].privkey) # paid in BTC to wallets[0] testlib.blockstack_name_renew("foo.test3", wallets[3].privkey) # paid in Stacks testlib.next_block(**kw) wallet_after_burn = testlib.get_balance(wallets[0].addr) if wallet_after_burn - wallet_before_burn != btc_price: print 'foo.test2 did not pay {} to {} (but paid {})'.format( btc_price, wallets[0].addr, wallet_after_burn - wallet_before_burn) return False # should all fail--wrong burn addresses testlib.blockstack_name_renew("foo.test1", pk, price={ 'units': 'STACKS', 'amount': stacks_price }, burn_addr=wallets[0].addr, safety_checks=False, expect_fail=True) testlib.blockstack_name_renew("bar.test1", wallets[3].privkey, burn_addr=wallets[0].addr, safety_checks=False, expect_fail=True) testlib.blockstack_name_renew("foo.test2", wallets[3].privkey, burn_addr=wallets[1].addr, safety_checks=False, expect_fail=True) testlib.blockstack_name_renew("foo.test3", wallets[3].privkey, burn_addr=wallets[0].addr, safety_checks=False, expect_fail=True) testlib.next_block(**kw) testlib.expect_snv_fail_at('foo.test1', testlib.get_current_block(**kw)) testlib.expect_snv_fail_at('bar.test1', testlib.get_current_block(**kw)) testlib.expect_snv_fail_at('foo.test2', testlib.get_current_block(**kw)) testlib.expect_snv_fail_at('foo.test3', testlib.get_current_block(**kw))
def scenario(wallets, **kw): print '\nactivating segwit\n' virtualchain.set_features("segwit", True) print '\nsegwit state: {}\n'.format(virtualchain.get_features('segwit')) testlib.blockstack_namespace_preorder("test", wallets[1].addr, wallets[5].privkey) testlib.blockstack_namespace_preorder("mult", wallets[2].addr, wallets[0].privkey) testlib.next_block(**kw) testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10, wallets[5].privkey) testlib.blockstack_namespace_reveal( "mult", wallets[2].addr, 52595, 250, 4, [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10, wallets[0].privkey, version_bits=2) testlib.next_block(**kw) private_keychain = keychain.PrivateKeychain.from_private_key( wallets[2].privkey) private_keys = [ wallets[2].privkey ] # NOTE: always start with the reveal key, then use children for i in xrange(0, 4): import_key = private_keychain.child(i).private_key() print "fund {} (child {})".format(import_key, i) res = testlib.send_funds( wallets[1].privkey, 100000000, virtualchain.BitcoinPrivateKey(import_key).public_key().address()) if 'error' in res: print json.dumps(res, indent=4, sort_keys=True) return False testlib.next_block(**kw) private_keys.append(import_key) # should succeed resp = testlib.blockstack_name_import("foo.mult", wallets[2].addr, '00' * 20, private_keys[0]) if 'error' in resp: print json.dumps(resp, indent=4, sort_keys=True) return False testlib.next_block(**kw) # should succeed resp = testlib.blockstack_name_import("bar.mult", wallets[3].addr, "11" * 20, private_keys[1]) if 'error' in resp: print json.dumps(resp, indent=4, sort_keys=True) return False # should succeed resp = testlib.blockstack_name_import("baz.mult", wallets[4].addr, "22" * 20, private_keys[2]) if 'error' in resp: print json.dumps(resp, indent=4, sort_keys=True) return False # should succeed resp = testlib.blockstack_name_import("goo.mult", wallets[5].addr, "33" * 20, private_keys[3]) if 'error' in resp: print json.dumps(resp, indent=4, sort_keys=True) return False testlib.next_block(**kw) testlib.blockstack_namespace_ready("test", wallets[1].privkey) testlib.blockstack_namespace_ready("mult", wallets[2].privkey) testlib.next_block(**kw) namespace_balance = testlib.get_balance(wallets[0].addr) # get prices hello_cost = testlib.blockstack_get_name_cost('hello.mult') world_cost = testlib.blockstack_get_name_cost('world.mult') foo_cost = testlib.blockstack_get_name_cost('foo.mult') # register/renew res = testlib.blockstack_name_preorder("hello.mult", wallets[1].privkey, wallets[2].addr) if 'error' in res: print res return False res = testlib.blockstack_name_preorder('world.mult', wallets[6].privkey, wallets[7].addr, wallet=wallets[7]) if 'error' in res: print res return False res = testlib.blockstack_name_renew('foo.mult', wallets[2].privkey) if 'error' in res: print res return False testlib.next_block(**kw) new_namespace_balance = testlib.get_balance(wallets[0].addr) if new_namespace_balance != namespace_balance + hello_cost + world_cost + foo_cost: print 'wrong balance' print new_namespace_balance print namespace_balance print hello_cost print foo_cost return False res = testlib.blockstack_name_register("hello.mult", wallets[1].privkey, wallets[2].addr) if 'error' in res: print res return False res = testlib.blockstack_name_register('world.mult', wallets[6].privkey, wallets[7].addr, wallet=wallets[7], zonefile_hash='44' * 20) if 'error' in res: print res return False testlib.next_block(**kw)
def scenario(wallets, **kw): global owner_address testlib.ysi_namespace_preorder("test", wallets[1].addr, wallets[0].privkey) testlib.next_block(**kw) testlib.ysi_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10, wallets[0].privkey) testlib.next_block(**kw) testlib.ysi_namespace_ready("test", wallets[1].privkey) testlib.next_block(**kw) # pre-0.13 wallet legacy_wallet = testlib.make_legacy_014_wallet(wallets[2].privkey, wallets[4].privkey, wallets[0].privkey, "0123456789abcdef") testlib.store_wallet(legacy_wallet) res = testlib.ysi_cli_setup_wallet("0123456789abcdef") if 'error' in res: print json.dumps(res, indent=4, sort_keys=True) return False if not res.has_key('backup_wallet'): print "no backup_wallet" print json.dumps(res, indent=4, sort_keys=True) return False if not os.path.exists(res['backup_wallet']): print "backup wallet doesn't exist" print json.dumps(res, indent=4, sort_keys=True) return False res = testlib.instantiate_wallet() if 'error' in res: print json.dumps(res, indent=4, sort_keys=True) return False payment_address = str(res['payment_address']) owner_address = str(res['owner_address']) # fill wallet with 5 BTC res = testlib.send_funds(wallets[3].privkey, 5 * 10**8, payment_address) if 'error' in res: print "failed to fill wallet" print json.dumps(res) return False testlib.next_block(**kw) # register resp = testlib.ysi_cli_register("foo.test", "0123456789abcdef") if 'error' in resp: print >> sys.stderr, json.dumps(resp, indent=4, sort_keys=True) return False # wait for the preorder to get confirmed for i in xrange(0, 12): testlib.next_block(**kw) # wait for the poller to pick it up print >> sys.stderr, "Waiting 10 seconds for the backend to submit the register" time.sleep(10) # wait for the register to get confirmed for i in xrange(0, 12): testlib.next_block(**kw) print >> sys.stderr, "Waiting 10 seconds for the backend to acknowledge registration" time.sleep(10) # wait for update to get confirmed for i in xrange(0, 12): testlib.next_block(**kw) print >> sys.stderr, "Waiting 10 seconds for the backend to acknowledge update" time.sleep(10)
def scenario(wallets, **kw): # has the side-effect of starting the API server resp = testlib.blockstack_client_initialize_wallet("0123456789abcdef", wallets[2].privkey, wallets[3].privkey, wallets[4].privkey) if 'error' in resp: print json.dumps(resp, indent=4, sort_keys=True) return False resp = testlib.blockstack_cli_namespace_preorder("test", wallets[0].privkey, wallets[1].privkey) if 'error' in resp: print json.dumps(resp, indent=4, sort_keys=True) return False testlib.next_block(**kw) resp = testlib.blockstack_cli_namespace_reveal( 'test', wallets[0].privkey, wallets[1].privkey, 52560, 4, 4, '6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0', 10, 10) if 'error' in resp: print json.dumps(resp, indent=4, sort_keys=True) return False testlib.next_block(**kw) private_keychain = keychain.PrivateKeychain.from_private_key( wallets[1].privkey) private_keys = [ wallets[1].privkey ] # NOTE: always start with the reveal key, then use children for i in xrange(0, 4): import_key = private_keychain.child(i).private_key() print "fund {} (child {})".format(import_key, i) res = testlib.send_funds( wallets[1].privkey, 100000000, virtualchain.BitcoinPrivateKey(import_key).public_key().address()) if 'error' in res: print json.dumps(res, indent=4, sort_keys=True) return False testlib.next_block(**kw) private_keys.append(import_key) # should fail (first key must be revealer) resp = testlib.blockstack_cli_name_import("fail.test", wallets[2].addr, "Hello fail.test!", private_keys[1]) if 'error' not in resp: print json.dumps(resp, indent=4, sort_keys=True) return False # should succeed resp = testlib.blockstack_cli_name_import("foo.test", wallets[2].addr, "Hello foo.test!", private_keys[0]) if 'error' in resp: print json.dumps(resp, indent=4, sort_keys=True) return False testlib.next_block(**kw) # 3 in one block (zero-conf) resp = testlib.blockstack_cli_name_import("bar.test", wallets[3].addr, "Hello bar.test!", private_keys[1]) if 'error' in resp: print json.dumps(resp, indent=4, sort_keys=True) return False resp = testlib.blockstack_cli_name_import("baz.test", wallets[4].addr, "Hello baz.test!", private_keys[2]) if 'error' in resp: print json.dumps(resp, indent=4, sort_keys=True) return False resp = testlib.blockstack_cli_name_import("goo.test", wallets[5].addr, "Hello goo.test!", private_keys[3]) if 'error' in resp: print json.dumps(resp, indent=4, sort_keys=True) return False testlib.next_block(**kw) # should fail (wrong key) resp = testlib.blockstack_cli_name_import("fail.test", wallets[5].addr, "Hello fail.test!", wallets[2].privkey) if 'error' not in resp: print json.dumps(resp, indent=4, sort_keys=True) return False resp = testlib.blockstack_cli_namespace_ready('test', wallets[1].privkey) if 'error' in resp: print json.dumps(resp, indent=4, sort_keys=True) return False for i in xrange(0, 10): testlib.next_block(**kw) print "Waiting 10 seconds for registrar to replicate zone files" time.sleep(10)
def scenario( wallets, **kw ): patch_file_contents = '\n'.join(patch_file_addrs) h = hashlib.new('sha256') h.update(patch_file_contents) patch_file_hash = h.hexdigest() with open(patch_addrs_path, 'w') as f: f.write(patch_file_contents) for k in genesis_patches_files: genesis_patches_files[k]['sha256'] = patch_file_hash blockstack.lib.config.set_genesis_block_patches(genesis_patches) blockstack.lib.config.set_genesis_block_patches_files(genesis_patches_files) testlib.set_account_audits(False) # in block 689, so the patch hasn't taken place yet balances = testlib.get_wallet_balances(wallets) assert balances[wallets[0].addr][STACKS] == 100 + 600000 assert balances[wallets[1].addr][STACKS] == 123 + 1000 assert balances[wallets[2].addr][STACKS] == 0 # send some tokens to a brand-new address testlib.blockstack_send_tokens(new_addr, "STACKS", 600000, wallets[0].privkey) testlib.blockstack_send_tokens(new_unlocked_addr, "STACKS", 100, wallets[0].privkey) testlib.next_block(**kw) # end of 689, triggers vesting of block 690 assert virtualchain.lib.indexer.StateEngine.get_block_statistics(testlib.get_current_block(**kw))['num_processed_ops'] == 2 # new balances should reflect patch balances = testlib.get_addr_balances([w.addr for w in wallets] + [new_addr_b58, new_grant_addr_b58, new_unlocked_addr_b58]) print balances assert balances[wallets[0].addr][STACKS] == 100 + 200 + 600000 + 600001 + 10000 + 10001 + 10002 + 10003 + 10004 + 10005 - 600000 - 100 # += new value + retroactive vesting assert balances[wallets[1].addr][STACKS] == 123 + 1000 + (10000000 * 10) assert balances[wallets[2].addr][STACKS] == 123456 assert balances[new_addr_b58][STACKS] == 600000 + 222222 + 66 assert balances[new_grant_addr_b58][STACKS] == 567 + (10000000 * 10) assert balances[new_unlocked_addr_b58][STACKS] == 100 + 123456 + 22000 + 22001 + 22002 + 22003 + 22004 + 22005 # send some tokens to a brand-new address # should be transfer-locked testlib.blockstack_send_tokens(new_addr_b58, "STACKS", 600000, wallets[0].privkey, safety_checks=False, expect_fail=True) testlib.blockstack_send_tokens(new_grant_addr_b58, "STACKS", 1, new_wallet, safety_checks=False, expect_fail=True) testlib.blockstack_send_tokens(new_grant_addr_b58, "STACKS", 10000000, wallets[1].privkey, safety_checks=False) testlib.blockstack_send_tokens(new_addr_b58, "STACKS", 10000000, wallets[1].privkey, safety_checks=False) testlib.blockstack_send_tokens(new_grant_addr_b58, "STACKS", 3, new_unlocked_wallet, safety_checks=False) testlib.next_block(**kw) # 690 assert virtualchain.lib.indexer.StateEngine.get_block_statistics(testlib.get_current_block(**kw))['num_processed_ops'] == 3 balances = testlib.get_addr_balances([w.addr for w in wallets] + [new_addr_b58, new_grant_addr_b58, new_unlocked_addr_b58]) print balances assert balances[wallets[0].addr][STACKS] == 100 + 200 + 600000 + 600001 + 600010 + 10000 + 10001 + 10002 + 10003 + 10004 + 10005 + 10006 - 600000 - 100 # += new value + retroactive vesting assert balances[wallets[1].addr][STACKS] == 123 + 1000 + (10000000 * 10) - 10000000 - 10000000 assert balances[wallets[2].addr][STACKS] == 123456 assert balances[new_addr_b58][STACKS] == 600000 + 222222 + 66 + 10000000 assert balances[new_grant_addr_b58][STACKS] == 567 + (10000000 * 10) + 10000000 + 3 assert balances[new_unlocked_addr_b58][STACKS] == 100 + 123456 + 22000 + 22001 + 22002 + 22003 + 22004 + 22005 + 22006 - 3 # apply patches from files balances = testlib.get_addr_balances(patch_file_addrs[0:5]) print balances for addr in patch_file_addrs[0:5]: assert balances[addr].get(STACKS, 0) == 0 testlib.next_block(**kw) # make the balances real (end of 691) balances = testlib.get_addr_balances(patch_file_addrs[0:5]) for addr in patch_file_addrs[0:5]: assert balances[addr][STACKS] == 12345 # apply patches from files balances_before_patch = testlib.get_addr_balances(patch_file_addrs[5:8]) print balances_before_patch assert balances_before_patch[new_addr_b58][STACKS] == 600000 + 222222 + 66 + 10000000 assert balances_before_patch[new_grant_addr_b58][STACKS] == 567 + (10000000 * 10) + 10000000 + 3 assert balances_before_patch[new_unlocked_addr_b58][STACKS] == 100 + 123456 + 22000 + 22001 + 22002 + 22003 + 22004 + 22005 + 22006 + 22007 - 3 testlib.next_block(**kw) # make the balances real (end of 692) balances_after_patch = testlib.get_addr_balances(patch_file_addrs[5:8]) assert balances_after_patch[new_addr_b58][STACKS] == 600000 + 222222 + 66 + 10000000 + 23456 assert balances_after_patch[new_grant_addr_b58][STACKS] == 567 + (10000000 * 10) + 10000000 + 3 + 23456 assert balances_after_patch[new_unlocked_addr_b58][STACKS] == 100 + 123456 + 22000 + 22001 + 22002 + 22003 + 22004 + 22005 + 22006 + 22007 + 22008 - 3 + 23456 # drain-transfer from newly-granted for (addr, privkey) in zip(patch_file_addrs[0:5], patch_file_privkeys): testlib.send_funds(wallets[0].privkey, 388500, virtualchain.address_reencode(addr)) testlib.blockstack_send_tokens(new_addr_b58, "STACKS", 12345, privkey) testlib.next_block(**kw) balances_after_xfer = testlib.get_addr_balances(patch_file_addrs) print balances_after_xfer for addr in patch_file_addrs[0:5]: assert balances_after_xfer[addr].get(STACKS, 0) == 0 assert balances_after_xfer[new_addr_b58][STACKS] == 600000 + 222222 + 66 + 10000000 + 23456 + 12345*5 assert balances_after_xfer[new_grant_addr_b58][STACKS] == 567 + (10000000 * 10) + 10000000 + 3 + 23456 assert balances_after_xfer[new_unlocked_addr_b58][STACKS] == 100 + 123456 + 22000 + 22001 + 22002 + 22003 + 22004 + 22005 + 22006 + 22007 + 22008 + 22009 - 3 + 23456
def scenario(wallets, **kw): global pk testlib.blockstack_namespace_preorder("test", wallets[1].addr, wallets[0].privkey) testlib.next_block(**kw) testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10, wallets[0].privkey) testlib.next_block(**kw) testlib.blockstack_namespace_ready("test", wallets[1].privkey) testlib.next_block(**kw) # pay for a name in a v1 namespace with Stacks addr = virtualchain.address_reencode(virtualchain.get_privkey_address(pk)) # calculate the cost of doing so namespace = testlib.get_state_engine().get_namespace('test') stacks_price = blockstack.lib.scripts.price_name_stacks( 'foo', namespace, testlib.get_current_block(**kw)) btc_price = blockstack.lib.scripts.price_name( 'foo', namespace, testlib.get_current_block(**kw)) print '' print 'price of {} in Stacks is {}'.format('foo.test', stacks_price) print '' testlib.blockstack_send_tokens(addr, "STACKS", stacks_price * 4, wallets[0].privkey) testlib.send_funds(wallets[0].privkey, btc_price * 10, addr) # fund with enough bitcoin testlib.next_block(**kw) # preorder/register using Stacks---Stacks should still be used since that's what the transaction indicates testlib.blockstack_name_preorder("foo.test", pk, wallets[3].addr, price={ 'units': 'STACKS', 'amount': stacks_price }) testlib.next_block(**kw) testlib.send_funds(wallets[0].privkey, btc_price * 10, addr) testlib.blockstack_name_register("foo.test", pk, wallets[3].addr) testlib.next_block(**kw) # preorder/register using Bitcoin--Stacks should NOT be used since that's what the transaction indicates testlib.blockstack_name_preorder("bar.test", pk, wallets[3].addr, price={ 'units': 'BTC', 'amount': btc_price }) testlib.next_block(**kw) testlib.blockstack_name_register('bar.test', pk, wallets[3].addr) testlib.next_block(**kw) balance_before = testlib.get_addr_balances(addr)[addr]['STACKS'] # pay with Stacks and Bitcoin. Preorder should succeed, and register should also succeed since we're paying enough stacks. Underpay bitcoin res = testlib.blockstack_name_preorder('baz.test', pk, wallets[3].addr, price={ 'units': 'STACKS', 'amount': stacks_price }, tx_only=True, expect_success=True) txhex = res['transaction'] tx = virtualchain.btc_tx_deserialize(txhex) # up the burn amount btc_price = blockstack.lib.scripts.price_name( 'baz', namespace, testlib.get_current_block(**kw)) tx['outs'][2]['script'] = virtualchain.btc_make_payment_script( blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS) tx['outs'][2]['value'] = btc_price - 1 tx['outs'][1]['value'] -= btc_price - 1 # re-sign for i in tx['ins']: i['script'] = '' txhex = virtualchain.btc_tx_serialize(tx) txhex_signed = virtualchain.tx_sign_all_unsigned_inputs( pk, testlib.get_utxos(addr), txhex) print txhex_signed res = testlib.broadcast_transaction(txhex_signed) if 'error' in res: print res return False testlib.next_block(**kw) # should have paid in Stacks balance_after = testlib.get_addr_balances(addr)[addr]['STACKS'] if balance_after != balance_before - stacks_price: print 'baz.test cost {}'.format(balance_before - balance_after) return False # should succeed, since we paid enough stacks (Bitcoin is not considered) testlib.blockstack_name_register('baz.test', pk, wallets[3].addr) testlib.next_block(**kw) balance_before = testlib.get_addr_balances(addr)[addr]['STACKS'] # register a name where we pay not enough stacks, but enough bitcoin. preorder should succeed, but register should fail since we tried to use stacks res = testlib.blockstack_name_preorder('goo.test', pk, wallets[3].addr, price={ 'units': 'STACKS', 'amount': stacks_price - 1 }, tx_only=True, expect_success=True) txhex = res['transaction'] tx = virtualchain.btc_tx_deserialize(txhex) # up the burn amount to the name price btc_price = blockstack.lib.scripts.price_name( 'goo', namespace, testlib.get_current_block(**kw)) tx['outs'][2]['script'] = virtualchain.btc_make_payment_script( blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS) tx['outs'][2]['value'] = btc_price tx['outs'][1]['value'] -= btc_price # re-sign for i in tx['ins']: i['script'] = '' txhex = virtualchain.btc_tx_serialize(tx) txhex_signed = virtualchain.tx_sign_all_unsigned_inputs( pk, testlib.get_utxos(addr), txhex) print txhex_signed res = testlib.broadcast_transaction(txhex_signed) if 'error' in res: print res return False testlib.next_block(**kw) # should have paid in Stacks balance_after = testlib.get_addr_balances(addr)[addr]['STACKS'] if balance_after != balance_before - stacks_price + 1: print 'goo.test paid {}'.format(balance_before - balance_after) return False # should fail, since we tried to pay in stacks and didn't pay enough testlib.blockstack_name_register('goo.test', pk, wallets[3].addr) testlib.next_block(**kw) testlib.expect_snv_fail_at('goo.test', testlib.get_current_block(**kw)) if testlib.get_state_engine().get_name('goo.test') is not None: print 'registered goo.test' return False balance_before = testlib.get_addr_balances(addr)[addr]['STACKS'] # underpay in both Stacks and Bitcoin. # both stacks and bitcoin will be burned. # preorder should succeed, but register should fail. res = testlib.blockstack_name_preorder('nop.test', pk, wallets[3].addr, price={ 'units': 'STACKS', 'amount': stacks_price - 1 }, safety_checks=False, tx_only=True, expect_success=True) txhex = res['transaction'] tx = virtualchain.btc_tx_deserialize(txhex) # up the burn amount to the name price, but just under btc_price = blockstack.lib.scripts.price_name( 'nop', namespace, testlib.get_current_block(**kw)) tx['outs'][2]['script'] = virtualchain.btc_make_payment_script( blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS) tx['outs'][2]['value'] = btc_price - 1 tx['outs'][1]['value'] -= btc_price - 1 # re-sign for i in tx['ins']: i['script'] = '' txhex = virtualchain.btc_tx_serialize(tx) txhex_signed = virtualchain.tx_sign_all_unsigned_inputs( pk, testlib.get_utxos(addr), txhex) print txhex_signed res = testlib.broadcast_transaction(txhex_signed) if 'error' in res: print res return False testlib.next_block(**kw) # should fail, since we didn't pay enough stacks and tried to pay in stacks res = testlib.blockstack_name_register('nop.test', pk, wallets[3].addr) testlib.next_block(**kw) testlib.expect_snv_fail_at('nop.test', testlib.get_current_block(**kw)) # preorder should still have debited balance_after = testlib.get_addr_balances(addr)[addr]['STACKS'] if balance_after != balance_before - stacks_price + 1: print 'paid {} for nop.test'.format(balance_before - balance_after) return False
def scenario(wallets, **kw): global pk, pk2, pk3 testlib.blockstack_namespace_preorder("test", wallets[1].addr, wallets[0].privkey) testlib.next_block(**kw) testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10, wallets[0].privkey) testlib.next_block(**kw) testlib.blockstack_namespace_ready("test", wallets[1].privkey) testlib.next_block(**kw) # pay for a name in a v1 namespace with Stacks addr = virtualchain.address_reencode(virtualchain.get_privkey_address(pk)) addr2 = virtualchain.address_reencode( virtualchain.get_privkey_address(pk2)) addr3 = virtualchain.address_reencode( virtualchain.get_privkey_address(pk3)) # calculate the cost of doing so namespace = testlib.get_state_engine().get_namespace('test') stacks_price = blockstack.lib.scripts.price_name_stacks( 'foo', namespace, testlib.get_current_block(**kw)) btc_price = blockstack.lib.scripts.price_name( 'foo', namespace, testlib.get_current_block(**kw)) # try to preorder/register using not enough Bitcoin and not enough Bitcoin (should fail) print '' print 'price of {} in Stacks is {}'.format('foo.test', stacks_price) print 'price of {} in BTC is {}'.format('foo.test', btc_price) print '' testlib.send_funds(wallets[0].privkey, btc_price * 2, addr) # try to preorder/register using not enough bitcoin (preorder should succeed; register should fail) testlib.blockstack_name_preorder("foo.test", pk, wallets[3].addr, price={ 'units': 'BTC', 'amount': btc_price - 1 }, safety_checks=False) testlib.next_block(**kw) testlib.expect_snv_fail_at('foo.test', testlib.get_current_block(**kw)) testlib.blockstack_name_register("foo.test", pk, wallets[3].addr, safety_checks=False) testlib.next_block(**kw) testlib.expect_snv_fail_at('foo.test', testlib.get_current_block(**kw)) # pass tokens testlib.send_funds(wallets[0].privkey, btc_price * 2, addr2) testlib.blockstack_send_tokens(addr2, "STACKS", stacks_price, wallets[0].privkey) testlib.next_block(**kw) # try to preorder/register using not enough Stacks (preorder should succeed; register should fail) testlib.blockstack_name_preorder("foo.test", pk2, wallets[4].addr, price={ 'units': 'STACKS', 'amount': stacks_price - 1 }, safety_checks=False) testlib.next_block(**kw) testlib.expect_snv_fail_at('foo.test', testlib.get_current_block(**kw)) testlib.blockstack_name_register("foo.test", pk2, wallets[4].addr, safety_checks=False) testlib.next_block(**kw) testlib.expect_snv_fail_at('foo.test', testlib.get_current_block(**kw)) # pass tokens testlib.send_funds(wallets[0].privkey, btc_price * 2, addr3) testlib.blockstack_send_tokens(addr3, "STACKS", stacks_price, wallets[0].privkey) testlib.next_block(**kw) # try to preorder/register using the right amount of stacks, but not paying in BTC (should succeed) testlib.blockstack_name_preorder("foo.test", pk3, wallets[1].addr, price={ 'units': 'STACKS', 'amount': stacks_price }) testlib.next_block(**kw) testlib.blockstack_name_register("foo.test", pk3, wallets[1].addr) testlib.next_block(**kw)
def scenario(wallets, **kw): # make a test namespace resp = testlib.ysi_namespace_preorder("test", wallets[1].addr, wallets[0].privkey) if debug or 'error' in resp: print json.dumps(resp, indent=4) testlib.next_block(**kw) resp = testlib.ysi_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10, wallets[0].privkey) if debug or 'error' in resp: print json.dumps(resp, indent=4) testlib.next_block(**kw) # derive importer keys and do imports # NOTE: breaks consensus trace from 0.14.0 private_keychain = keychain.PrivateKeychain.from_private_key( wallets[1].privkey) private_keys = [ wallets[1].privkey ] # NOTE: always start with the reveal key, then use children for i in xrange(0, 3): import_key = private_keychain.child(i).private_key() print "fund {} (child {})".format(import_key, i) res = testlib.send_funds( wallets[1].privkey, 100000000, virtualchain.BitcoinPrivateKey(import_key).public_key().address()) if 'error' in res: print json.dumps(res, indent=4, sort_keys=True) return False testlib.next_block(**kw) private_keys.append(import_key) resp = testlib.ysi_name_import("foo.test", wallets[3].addr, "11" * 20, private_keys[0]) if 'error' in resp: print json.dumps(resp, indent=4) testlib.next_block(**kw) # import twice resp = testlib.ysi_name_import("bar.test", wallets[4].addr, "22" * 20, private_keys[0]) if 'error' in resp: print json.dumps(resp, indent=4) testlib.next_block(**kw) resp = testlib.ysi_name_import("bar.test", wallets[4].addr, "33" * 20, private_keys[1]) if 'error' in resp: print json.dumps(resp, indent=4) testlib.next_block(**kw) # import thrice in the same block resp = testlib.ysi_name_import("baz.test", wallets[5].addr, "44" * 20, private_keys[0]) if 'error' in resp: print json.dumps(resp, indent=4) resp = testlib.ysi_name_import("baz.test", wallets[5].addr, "55" * 20, private_keys[1]) if 'error' in resp: print json.dumps(resp, indent=4) resp = testlib.ysi_name_import("baz.test", wallets[5].addr, "66" * 20, private_keys[2]) if 'error' in resp: print json.dumps(resp, indent=4) testlib.next_block(**kw) # import all three in the same block resp = testlib.ysi_name_import("foo.test", wallets[5].addr, "66" * 20, private_keys[0]) if 'error' in resp: print json.dumps(resp, indent=4) resp = testlib.ysi_name_import("bar.test", wallets[3].addr, "77" * 20, private_keys[1]) if 'error' in resp: print json.dumps(resp, indent=4) resp = testlib.ysi_name_import("baz.test", wallets[4].addr, "88" * 20, private_keys[2]) if 'error' in resp: print json.dumps(resp, indent=4) testlib.next_block(**kw) # import thrice in the same block, again resp = testlib.ysi_name_import("baz.test", wallets[5].addr, "44" * 20, private_keys[0]) if 'error' in resp: print json.dumps(resp, indent=4) resp = testlib.ysi_name_import("baz.test", wallets[5].addr, "55" * 20, private_keys[1]) if 'error' in resp: print json.dumps(resp, indent=4) resp = testlib.ysi_name_import("baz.test", wallets[5].addr, "66" * 20, private_keys[2]) if 'error' in resp: print json.dumps(resp, indent=4) testlib.next_block(**kw) # import all three in the same block, again resp = testlib.ysi_name_import("foo.test", wallets[5].addr, "66" * 20, private_keys[0]) if 'error' in resp: print json.dumps(resp, indent=4) resp = testlib.ysi_name_import("bar.test", wallets[3].addr, "77" * 20, private_keys[1]) if 'error' in resp: print json.dumps(resp, indent=4) resp = testlib.ysi_name_import("baz.test", wallets[4].addr, "88" * 20, private_keys[2]) if 'error' in resp: print json.dumps(resp, indent=4) testlib.next_block(**kw) testlib.ysi_namespace_ready("test", wallets[1].privkey) testlib.next_block(**kw)
def scenario( wallets, **kw ): # make a test namespace resp = testlib.blockstack_namespace_preorder( "test", wallets[1].addr, wallets[0].privkey ) if debug or 'error' in resp: print json.dumps( resp, indent=4 ) testlib.next_block( **kw ) resp = testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0], 10, 10, wallets[0].privkey ) if debug or 'error' in resp: print json.dumps( resp, indent=4 ) testlib.next_block( **kw ) # import 3 names in the same block: foo.test, bar.test, baz.test names = ['foo.test', 'bar.test', 'baz.test'] name_preorder_wallets = [wallets[2], wallets[3], wallets[4]] name_register_wallets = [wallets[5], wallets[6], wallets[7]] name_transfer_wallets = [wallets[6], wallets[7], wallets[5]] # derive importer keys and do imports # NOTE: breaks consensus trace from 0.14.0 private_keychain = keychain.PrivateKeychain.from_private_key( wallets[1].privkey ) private_keys = [wallets[1].privkey] # NOTE: always start with the reveal key, then use children for i in xrange(0, len(names)-1): import_key = private_keychain.child(i).private_key() print "fund {} (child {})".format(import_key, i) res = testlib.send_funds( wallets[1].privkey, 100000000, virtualchain.BitcoinPrivateKey(import_key).public_key().address() ) if 'error' in res: print json.dumps(res, indent=4, sort_keys=True) return False testlib.next_block(**kw) private_keys.append(import_key) for i in xrange(0, len(names)): name = names[i] register_wallet = name_register_wallets[i] import_key = private_keys[i] resp = testlib.blockstack_name_import( name, register_wallet.addr, str(9 - i) * 40, import_key, safety_checks=False ) if debug or 'error' in resp: print json.dumps( resp, indent=4 ) testlib.next_block( **kw ) # namespace ready... resp = testlib.blockstack_namespace_ready( "test", wallets[1].privkey ) if debug or 'error' in resp: print json.dumps( resp, indent=4 ) testlib.next_block( **kw ) # update 3 names in the same block for i in xrange(0, len(names)): name = names[i] register_wallet = name_register_wallets[i] resp = testlib.blockstack_name_update( name, str(i + 2) * 40, register_wallet.privkey ) if debug or 'error' in resp: print json.dumps( resp, indent=4 ) testlib.next_block( **kw ) # update 3 names in the same block, again for i in xrange(0, len(names)): name = names[i] register_wallet = name_register_wallets[i] resp = testlib.blockstack_name_update( name, str(i + 1) * 40, register_wallet.privkey ) if debug or 'error' in resp: print json.dumps( resp, indent=4 ) testlib.next_block( **kw ) # transfer 3 names in the same block for i in xrange(0, len(names)): name = names[i] register_wallet = name_register_wallets[i] transfer_wallet = name_transfer_wallets[i] resp = testlib.blockstack_name_transfer( name, transfer_wallet.addr, True, register_wallet.privkey ) if debug or 'error' in resp: print json.dumps( resp, indent=4 ) testlib.next_block( **kw ) # exchange after transfer... tmp = name_register_wallets name_register_wallets = name_transfer_wallets name_transfer_wallets = tmp # revoke 3 names in the same block for i in xrange(0, len(names)): name = names[i] register_wallet = name_register_wallets[i] resp = testlib.blockstack_name_revoke( name, register_wallet.privkey ) if debug or 'error' in resp: print json.dumps( resp, indent=4 ) # iterate the blocks a few times for i in xrange(0, 5): testlib.next_block( **kw )
def scenario(wallets, **kw): testlib.blockstack_namespace_preorder("test", wallets[1].addr, wallets[0].privkey) testlib.next_block(**kw) testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10, wallets[0].privkey, version_bits=blockstack.lib.config.NAMESPACE_VERSION_PAY_TO_CREATOR) testlib.next_block(**kw) testlib.blockstack_namespace_ready("test", wallets[1].privkey) testlib.next_block(**kw) # pay for a name in a v1 namespace with Stacks addr = virtualchain.address_reencode(virtualchain.get_privkey_address(pk)) addr2 = virtualchain.address_reencode( virtualchain.get_privkey_address(pk2)) # calculate the cost of doing so namespace = testlib.get_state_engine().get_namespace('test') stacks_price = blockstack.lib.scripts.price_name_stacks( 'foo', namespace, testlib.get_current_block(**kw)) btc_price = blockstack.lib.scripts.price_name( 'foo', namespace, testlib.get_current_block(**kw)) print '' print 'price of {} in Stacks is {}'.format('foo.test', stacks_price) print 'price of {} in BTC is {}'.format('foo.test', btc_price) print '' testlib.blockstack_send_tokens(addr, "STACKS", stacks_price, wallets[0].privkey) testlib.blockstack_send_tokens(addr2, "STACKS", stacks_price, wallets[0].privkey) testlib.send_funds(wallets[0].privkey, 2 * btc_price, addr) testlib.send_funds(wallets[0].privkey, 2 * btc_price, addr2) testlib.next_block(**kw) # preorder/register using BTC testlib.blockstack_name_preorder("foo.test", pk, addr2) testlib.next_block(**kw) testlib.blockstack_name_register("foo.test", pk, addr2) testlib.next_block(**kw) # try to renew using Stacks (won't work, since we send tokens the wrong burn address) testlib.blockstack_name_renew( 'foo.test', pk2, price={ 'units': 'STACKS', 'amount': stacks_price }, burn_addr=blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS, safety_checks=False, expect_fail=True) testlib.next_block(**kw) # try to renew using Stacks (won't work, since we're still collecting fees in BTC and need to send to the namespace creator's address) testlib.blockstack_name_renew('foo.test', pk2, price={ 'units': 'STACKS', 'amount': stacks_price }, burn_addr=wallets[0].addr, safety_checks=False, expect_fail=True) testlib.next_block(**kw) # try to renew using Stacks, now that pay-to-creator has expired testlib.blockstack_name_renew('foo.test', pk2, price={ 'units': 'STACKS', 'amount': stacks_price }) testlib.next_block(**kw)
def scenario(wallets, **kw): global pk, pk2 testlib.blockstack_namespace_preorder("test", wallets[1].addr, wallets[0].privkey) testlib.next_block(**kw) testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10, wallets[0].privkey) testlib.next_block(**kw) testlib.blockstack_namespace_ready("test", wallets[1].privkey) testlib.next_block(**kw) # pay for a name in a v1 namespace with Stacks addr = virtualchain.address_reencode(virtualchain.get_privkey_address(pk)) addr2 = virtualchain.address_reencode( virtualchain.get_privkey_address(pk2)) # calculate the cost of doing so namespace = testlib.get_state_engine().get_namespace('test') stacks_price = blockstack.lib.scripts.price_name_stacks( 'baz', namespace, testlib.get_current_block(**kw)) btc_price = blockstack.lib.scripts.price_name( 'baz', namespace, testlib.get_current_block(**kw)) print '' print 'price of {} in Stacks is {}'.format('baz.test', stacks_price) print 'price of {} in BTC is {}'.format('baz.test', btc_price) print '' testlib.blockstack_send_tokens(addr, "STACKS", stacks_price, wallets[0].privkey) testlib.blockstack_send_tokens(addr2, "STACKS", stacks_price * 2, wallets[0].privkey) testlib.send_funds(wallets[0].privkey, 10 * btc_price, addr) testlib.send_funds(wallets[0].privkey, 10 * btc_price, addr2) testlib.next_block(**kw) # preorder/register using Stacks testlib.blockstack_name_preorder("baz.test", wallets[2].privkey, addr2, price={ 'units': 'STACKS', 'amount': stacks_price }) testlib.blockstack_name_preorder("goo.test", wallets[2].privkey, addr2, price={ 'units': 'STACKS', 'amount': stacks_price }) testlib.blockstack_name_preorder("nop.test", wallets[2].privkey, addr2, price={ 'units': 'STACKS', 'amount': stacks_price }) testlib.next_block(**kw) testlib.blockstack_name_register("baz.test", wallets[2].privkey, addr2) testlib.blockstack_name_register("goo.test", wallets[2].privkey, addr2) testlib.blockstack_name_register("nop.test", wallets[2].privkey, addr2) testlib.next_block(**kw) balance_before = testlib.get_addr_balances(addr2)[addr2]['STACKS'] # pay with both Stacks and Bitcoin # should favor Stacks payment over Bitcoin payment if we pay enough stacks. # Stacks should have been burned, as well as BTC. res = testlib.blockstack_name_renew('baz.test', pk2, price={ 'units': 'STACKS', 'amount': stacks_price }, tx_only=True, expect_success=True) txhex = res['transaction'] tx = virtualchain.btc_tx_deserialize(txhex) # up the burn amount btc_price = blockstack.lib.scripts.price_name( 'baz', namespace, testlib.get_current_block(**kw)) tx['outs'][3]['script'] = virtualchain.btc_make_payment_script( blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS) tx['outs'][3]['value'] = btc_price tx['outs'][4]['value'] -= btc_price # re-sign for i in tx['ins']: i['script'] = '' txhex = virtualchain.btc_tx_serialize(tx) txhex_signed = virtualchain.tx_sign_all_unsigned_inputs( pk2, testlib.get_utxos(addr2), txhex) # re-sign the last output with the payment key tx_signed = virtualchain.btc_tx_deserialize(txhex_signed) tx_signed['ins'][-1]['script'] = '' txhex_signed = virtualchain.tx_sign_all_unsigned_inputs( testlib.get_default_payment_wallet().privkey, testlib.get_utxos(testlib.get_default_payment_wallet().addr), virtualchain.btc_tx_serialize(tx_signed)) print txhex_signed res = testlib.broadcast_transaction(txhex_signed) if 'error' in res: print res return False testlib.next_block(**kw) # should have paid in Stacks balance_after = testlib.get_addr_balances(addr2)[addr2]['STACKS'] if balance_after != balance_before - stacks_price: print 'baz.test cost {}'.format(balance_before - balance_after) return False balance_before = testlib.get_addr_balances(addr2)[addr2]['STACKS'] # try to renew a name where we pay not enough stacks, but enough bitcoin. # should be rejected. res = testlib.blockstack_name_renew('goo.test', pk2, price={ 'units': 'STACKS', 'amount': stacks_price - 1 }, tx_only=True) txhex = res['transaction'] tx = virtualchain.btc_tx_deserialize(txhex) # up the burn amount to the name price btc_price = blockstack.lib.scripts.price_name( 'goo', namespace, testlib.get_current_block(**kw)) tx['outs'][3]['script'] = virtualchain.btc_make_payment_script( blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS) tx['outs'][3]['value'] = btc_price tx['outs'][4]['value'] -= btc_price # re-sign for i in tx['ins']: i['script'] = '' txhex = virtualchain.btc_tx_serialize(tx) txhex_signed = virtualchain.tx_sign_all_unsigned_inputs( pk2, testlib.get_utxos(addr2), txhex) # re-sign the last output with the payment key tx_signed = virtualchain.btc_tx_deserialize(txhex_signed) tx_signed['ins'][-1]['script'] = '' txhex_signed = virtualchain.tx_sign_all_unsigned_inputs( testlib.get_default_payment_wallet().privkey, testlib.get_utxos(testlib.get_default_payment_wallet().addr), virtualchain.btc_tx_serialize(tx_signed)) print txhex_signed res = testlib.broadcast_transaction(txhex_signed) if 'error' in res: print res return False testlib.next_block(**kw) # should NOT have paid in Stacks balance_after = testlib.get_addr_balances(addr2)[addr2]['STACKS'] if balance_after != balance_before: print 'goo.test paid {}'.format(balance_before - balance_after) return False balance_before = testlib.get_addr_balances(addr2)[addr2]['STACKS'] # underpay in both Stacks and Bitcoin. # only bitcoin will be burned; transaction will not be processed res = testlib.blockstack_name_renew('nop.test', pk2, price={ 'units': 'STACKS', 'amount': stacks_price - 1 }, tx_only=True) txhex = res['transaction'] tx = virtualchain.btc_tx_deserialize(txhex) # up the burn amount to the name price btc_price = blockstack.lib.scripts.price_name( 'goo', namespace, testlib.get_current_block(**kw)) tx['outs'][3]['script'] = virtualchain.btc_make_payment_script( blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS) tx['outs'][3]['value'] = btc_price - 1 tx['outs'][4]['value'] -= btc_price + 1 # re-sign for i in tx['ins']: i['script'] = '' txhex = virtualchain.btc_tx_serialize(tx) txhex_signed = virtualchain.tx_sign_all_unsigned_inputs( pk2, testlib.get_utxos(addr2), txhex) # re-sign the last output with the payment key tx_signed = virtualchain.btc_tx_deserialize(txhex_signed) tx_signed['ins'][-1]['script'] = '' txhex_signed = virtualchain.tx_sign_all_unsigned_inputs( testlib.get_default_payment_wallet().privkey, testlib.get_utxos(testlib.get_default_payment_wallet().addr), virtualchain.btc_tx_serialize(tx_signed)) print txhex_signed res = testlib.broadcast_transaction(txhex_signed) if 'error' in res: print res return False testlib.next_block(**kw) testlib.expect_snv_fail_at('nop.test', testlib.get_current_block(**kw)) balance_after = testlib.get_addr_balances(addr2)[addr2]['STACKS'] if balance_after != balance_before: print 'paid {} for nop.test'.format(balance_before - balance_after) return False
def scenario( wallets, **kw ): global owner_address testlib.blockstack_namespace_preorder( "test", wallets[1].addr, wallets[0].privkey ) testlib.next_block( **kw ) testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0], 10, 10, wallets[0].privkey ) testlib.next_block( **kw ) testlib.blockstack_namespace_ready( "test", wallets[1].privkey ) testlib.next_block( **kw ) # pre-0.13 wallet legacy_wallet = testlib.make_legacy_013_wallet( wallets[2].privkey, wallets[4].privkey, "0123456789abcdef" ) testlib.store_wallet( legacy_wallet ) res = testlib.blockstack_cli_setup_wallet("0123456789abcdef") if 'error' in res: print json.dumps(res, indent=4, sort_keys=True) return False if not res.has_key('backup_wallet'): print "no backup_wallet" print json.dumps(res, indent=4, sort_keys=True) return False if not os.path.exists(res['backup_wallet']): print "backup wallet doesn't exist" print json.dumps(res, indent=4, sort_keys=True) return False res = testlib.instantiate_wallet() if 'error' in res: print json.dumps(res, indent=4, sort_keys=True) return False payment_address = str(res['payment_address']) owner_address = str(res['owner_address']) # fill wallet with 5 BTC res = testlib.send_funds( wallets[3].privkey, 5 * 10**8, payment_address ) if 'error' in res: print "failed to fill wallet" print json.dumps(res) return False testlib.next_block( **kw ) # register resp = testlib.blockstack_cli_register( "foo.test", "0123456789abcdef" ) if 'error' in resp: print >> sys.stderr, json.dumps(resp, indent=4, sort_keys=True) return False # wait for the preorder to get confirmed for i in xrange(0, 12): testlib.next_block( **kw ) # wait for the poller to pick it up print >> sys.stderr, "Waiting 10 seconds for the backend to submit the register" time.sleep(10) # wait for the register to get confirmed for i in xrange(0, 12): testlib.next_block( **kw ) print >> sys.stderr, "Waiting 10 seconds for the backend to acknowledge registration" time.sleep(10) # wait for update to get confirmed for i in xrange(0, 12): testlib.next_block( **kw ) print >> sys.stderr, "Waiting 10 seconds for the backend to acknowledge update" time.sleep(10)
def scenario( wallets, **kw ): global pk, pk2 testlib.blockstack_namespace_preorder( "test", wallets[1].addr, wallets[0].privkey ) testlib.next_block( **kw ) testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6,6,6,6,6,6,0,0,0,0,0,0,0,0,0,0], 10, 10, wallets[0].privkey, version_bits=blockstack.lib.config.NAMESPACE_VERSION_PAY_TO_CREATOR) testlib.next_block( **kw ) testlib.blockstack_namespace_ready( "test", wallets[1].privkey ) testlib.next_block( **kw ) # pay for a name in a v1 namespace with Stacks addr = virtualchain.address_reencode(virtualchain.get_privkey_address(pk)) addr2 = virtualchain.address_reencode(virtualchain.get_privkey_address(pk2)) # calculate the cost of doing so namespace = testlib.get_state_engine().get_namespace('test') stacks_price = blockstack.lib.scripts.price_name_stacks('foo', namespace, testlib.get_current_block(**kw)) btc_price = blockstack.lib.scripts.price_name('foo', namespace, testlib.get_current_block(**kw)) print '' print 'price of {} in Stacks is {}'.format('foo.test', stacks_price) print '' testlib.blockstack_send_tokens(addr, "STACKS", stacks_price * 8, wallets[0].privkey) testlib.blockstack_send_tokens(addr2, "STACKS", stacks_price * 8, wallets[0].privkey) testlib.send_funds(wallets[0].privkey, btc_price * 10, addr) # fund with enough bitcoin testlib.send_funds(wallets[0].privkey, btc_price * 10, addr2) # fund with enough bitcoin testlib.next_block(**kw) def _tx_pay_btc(txhex, privk, btc_paid, burn_addr): tx = virtualchain.btc_tx_deserialize(txhex) # up the burn amount btc_price = blockstack.lib.scripts.price_name('baz', namespace, testlib.get_current_block(**kw)) tx['outs'][2]['script'] = virtualchain.btc_make_payment_script(burn_addr) tx['outs'][2]['value'] = btc_paid tx['outs'][1]['value'] -= btc_paid # re-sign for i in tx['ins']: i['script'] = '' txhex = virtualchain.btc_tx_serialize(tx) _addr = virtualchain.address_reencode(virtualchain.get_privkey_address(privk)) txhex_signed = virtualchain.tx_sign_all_unsigned_inputs(privk, testlib.get_utxos(_addr), txhex) print txhex_signed res = testlib.broadcast_transaction(txhex_signed) assert 'error' not in res, res['error'] return res balance_before = testlib.get_addr_balances(addr)[addr]['STACKS'] # pay with Stacks and Bitcoin. Preorder should succeed only when we use the Blockstack burn address, but register should fail since we're paying Stacks. Pay enough bitcoin as well. res_fooa = testlib.blockstack_name_preorder('fooa.test', pk, wallets[3].addr, price={'units': 'STACKS', 'amount': stacks_price}, burn_addr=blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS, tx_only=True, expect_success=True, safety_checks=False) res_fooa = _tx_pay_btc(res_fooa['transaction'], pk, btc_price, blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS) res_bara = testlib.blockstack_name_preorder('bara.test', pk, wallets[3].addr, price={'units': 'STACKS', 'amount': stacks_price}, burn_addr=wallets[0].addr, tx_only=True, safety_checks=False) res_bara = _tx_pay_btc(res_bara['transaction'], pk, btc_price, wallets[0].addr) res_baza = testlib.blockstack_name_preorder('baza.test', pk, wallets[3].addr, price={'units': 'STACKS', 'amount': stacks_price - 1}, burn_addr=blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS, tx_only=True, expect_success=True, safety_checks=False) res_baza = _tx_pay_btc(res_baza['transaction'], pk, btc_price, blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS) res_gooa = testlib.blockstack_name_preorder('gooa.test', pk, wallets[3].addr, price={'units': 'STACKS', 'amount': stacks_price - 1}, burn_addr=wallets[0].addr, tx_only=True, safety_checks=False) res_gooa = _tx_pay_btc(res_gooa['transaction'], pk, btc_price, wallets[0].addr) res_foob = testlib.blockstack_name_preorder('foob.test', pk, wallets[3].addr, price={'units': 'STACKS', 'amount': stacks_price}, burn_addr=blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS, tx_only=True, expect_success=True, safety_checks=False) res_foob = _tx_pay_btc(res_foob['transaction'], pk, btc_price - 1, blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS) res_barb = testlib.blockstack_name_preorder('barb.test', pk, wallets[3].addr, price={'units': 'STACKS', 'amount': stacks_price}, burn_addr=wallets[0].addr, tx_only=True, safety_checks=False) res_barb = _tx_pay_btc(res_barb['transaction'], pk, btc_price - 1, wallets[0].addr) res_bazb = testlib.blockstack_name_preorder('bazb.test', pk, wallets[3].addr, price={'units': 'STACKS', 'amount': stacks_price - 1}, burn_addr=blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS, tx_only=True, expect_success=True, safety_checks=False) res_bazb = _tx_pay_btc(res_bazb['transaction'], pk, btc_price - 1, blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS) res_goob = testlib.blockstack_name_preorder('goob.test', pk, wallets[3].addr, price={'units': 'STACKS', 'amount': stacks_price - 1}, burn_addr=wallets[0].addr, tx_only=True, safety_checks=False) res_goob = _tx_pay_btc(res_goob['transaction'], pk, btc_price - 1, wallets[0].addr) testlib.next_block(**kw) # should have paid in Stacks for each preorder balance_after = testlib.get_addr_balances(addr)[addr]['STACKS'] if balance_after != balance_before - (2 * stacks_price + 2 * stacks_price - 2): print 'names cost {}'.format(balance_before - balance_after) return False # should all fail since we tried to pay in stacks at this time testlib.blockstack_name_register('fooa.test', pk, wallets[3].addr) testlib.blockstack_name_register('bara.test', pk, wallets[3].addr) testlib.blockstack_name_register('baza.test', pk, wallets[3].addr) testlib.blockstack_name_register('gooa.test', pk, wallets[3].addr) testlib.blockstack_name_register('foob.test', pk, wallets[3].addr) testlib.blockstack_name_register('barb.test', pk, wallets[3].addr) testlib.blockstack_name_register('bazb.test', pk, wallets[3].addr) testlib.blockstack_name_register('goob.test', pk, wallets[3].addr) testlib.next_block(**kw) # pay-to-creator ends testlib.expect_snv_fail_at('fooa.test', testlib.get_current_block(**kw)) testlib.expect_snv_fail_at('bara.test', testlib.get_current_block(**kw)) testlib.expect_snv_fail_at('baza.test', testlib.get_current_block(**kw)) testlib.expect_snv_fail_at('gooa.test', testlib.get_current_block(**kw)) testlib.expect_snv_fail_at('foob.test', testlib.get_current_block(**kw)) testlib.expect_snv_fail_at('barb.test', testlib.get_current_block(**kw)) testlib.expect_snv_fail_at('bazb.test', testlib.get_current_block(**kw)) testlib.expect_snv_fail_at('goob.test', testlib.get_current_block(**kw)) balance_before = testlib.get_addr_balances(addr2)[addr2]['STACKS'] # pay with Stacks and Bitcoin, now that pay-to-creator has passed. Preorder should succeed when we pay to blockstack burn address, and register should succeed (when we fund enough), all because we paid in stacks. res_fooa = testlib.blockstack_name_preorder('fooa.test', pk2, wallets[3].addr, price={'units': 'STACKS', 'amount': stacks_price}, burn_addr=blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS, tx_only=True, expect_success=True, safety_checks=False) res_fooa = _tx_pay_btc(res_fooa['transaction'], pk2, btc_price, blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS) res_bara = testlib.blockstack_name_preorder('bara.test', pk2, wallets[3].addr, price={'units': 'STACKS', 'amount': stacks_price}, burn_addr=wallets[0].addr, tx_only=True, safety_checks=False) res_bara = _tx_pay_btc(res_bara['transaction'], pk2, btc_price, wallets[0].addr) res_baza = testlib.blockstack_name_preorder('baza.test', pk2, wallets[3].addr, price={'units': 'STACKS', 'amount': stacks_price - 1}, burn_addr=blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS, tx_only=True, expect_success=True, safety_checks=False) res_baza = _tx_pay_btc(res_baza['transaction'], pk2, btc_price, blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS) res_gooa = testlib.blockstack_name_preorder('gooa.test', pk2, wallets[3].addr, price={'units': 'STACKS', 'amount': stacks_price - 1}, burn_addr=wallets[0].addr, tx_only=True, safety_checks=False) res_gooa = _tx_pay_btc(res_gooa['transaction'], pk2, btc_price, wallets[0].addr) res_foob = testlib.blockstack_name_preorder('foob.test', pk2, wallets[3].addr, price={'units': 'STACKS', 'amount': stacks_price}, burn_addr=blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS, tx_only=True, expect_success=True, safety_checks=False) res_foob = _tx_pay_btc(res_foob['transaction'], pk2, btc_price - 1, blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS) res_barb = testlib.blockstack_name_preorder('barb.test', pk2, wallets[3].addr, price={'units': 'STACKS', 'amount': stacks_price}, burn_addr=wallets[0].addr, tx_only=True, safety_checks=False) res_barb = _tx_pay_btc(res_barb['transaction'], pk2, btc_price - 1, wallets[0].addr) res_bazb = testlib.blockstack_name_preorder('bazb.test', pk2, wallets[3].addr, price={'units': 'STACKS', 'amount': stacks_price - 1}, burn_addr=blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS, tx_only=True, expect_success=True, safety_checks=False) res_bazb = _tx_pay_btc(res_bazb['transaction'], pk2, btc_price - 1, blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS) res_goob = testlib.blockstack_name_preorder('goob.test', pk2, wallets[3].addr, price={'units': 'STACKS', 'amount': stacks_price - 1}, burn_addr=wallets[0].addr, tx_only=True, safety_checks=False) res_goob = _tx_pay_btc(res_goob['transaction'], pk2, btc_price - 1, wallets[0].addr) testlib.next_block(**kw) # should have paid in Stacks for each preorder balance_after = testlib.get_addr_balances(addr2)[addr2]['STACKS'] if balance_after != balance_before - (2 * stacks_price + 2 * stacks_price - 2): print 'baz.test cost {}'.format(balance_before - balance_after) return False # only foo*.test should succeed, since we both paid enough stacks and paid to the burn address testlib.blockstack_name_register('fooa.test', pk2, wallets[3].addr) testlib.blockstack_name_register('bara.test', pk2, wallets[3].addr) testlib.blockstack_name_register('baza.test', pk2, wallets[3].addr) testlib.blockstack_name_register('gooa.test', pk2, wallets[3].addr) testlib.blockstack_name_register('foob.test', pk2, wallets[3].addr) testlib.blockstack_name_register('barb.test', pk2, wallets[3].addr) testlib.blockstack_name_register('bazb.test', pk2, wallets[3].addr) testlib.blockstack_name_register('goob.test', pk2, wallets[3].addr) testlib.next_block(**kw) testlib.expect_snv_fail_at('bara.test', testlib.get_current_block(**kw)) testlib.expect_snv_fail_at('baza.test', testlib.get_current_block(**kw)) testlib.expect_snv_fail_at('gooa.test', testlib.get_current_block(**kw)) testlib.expect_snv_fail_at('barb.test', testlib.get_current_block(**kw)) testlib.expect_snv_fail_at('bazb.test', testlib.get_current_block(**kw)) testlib.expect_snv_fail_at('goob.test', testlib.get_current_block(**kw))
def scenario(wallets, **kw): global pk testlib.blockstack_namespace_preorder("test", wallets[1].addr, wallets[0].privkey) testlib.next_block(**kw) # all names below are the same price testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 1, 1, wallets[0].privkey, version_bits=blockstack.lib.config.NAMESPACE_VERSION_PAY_TO_CREATOR) testlib.next_block(**kw) testlib.blockstack_namespace_ready("test", wallets[1].privkey) testlib.next_block(**kw) # pay for a name in a v1 namespace with Stacks addr = virtualchain.address_reencode(virtualchain.get_privkey_address(pk)) # calculate the cost of doing so namespace = testlib.get_state_engine().get_namespace('test') stacks_price = blockstack.lib.scripts.price_name_stacks( 'foo', namespace, testlib.get_current_block(**kw)) btc_price = blockstack.lib.scripts.price_name( 'foo', namespace, testlib.get_current_block(**kw)) print '' print 'price of {} in Stacks is {}'.format('foo.test', stacks_price) print '' testlib.blockstack_send_tokens(addr, "STACKS", stacks_price * 5, wallets[0].privkey) testlib.send_funds(wallets[0].privkey, btc_price * 10, addr) testlib.next_block(**kw) # preorder/register using Stacks (preorders should fail since we're using the wrong burn address for tokens) testlib.blockstack_name_preorder("foo.test", pk, wallets[3].addr, price={ 'units': 'STACKS', 'amount': stacks_price }, burn_addr=wallets[0].addr, safety_checks=False, expect_fail=True) testlib.blockstack_name_preorder("bar.test", pk, wallets[3].addr, price={ 'units': 'STACKS', 'amount': stacks_price - 1 }, burn_addr=wallets[0].addr, safety_checks=False, expect_fail=True) testlib.next_block(**kw) op_info = virtualchain.lib.indexer.StateEngine.get_block_statistics( testlib.get_current_block(**kw)) if op_info['num_processed_ops'] > 0: print 'handled ops this block' print op_info return False # preorder/register using Stacks (preorders should be accepted, but bar2 will fail to register) testlib.blockstack_name_preorder( "foo2.test", pk, wallets[2].addr, price={ 'units': 'STACKS', 'amount': stacks_price }, burn_addr=blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS, safety_checks=False) testlib.blockstack_name_preorder( "bar2.test", pk, wallets[2].addr, price={ 'units': 'STACKS', 'amount': stacks_price - 1 }, burn_addr=blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS, safety_checks=False) testlib.next_block(**kw) # preorder/register using Stacks (preorders should succeed now, but bar3.test will fail to register since we're not paying enough stacks) testlib.blockstack_name_register( "bar2.test", pk, wallets[2].addr ) # should fail at this point, since the preorder sent to the wrong burn address testlib.blockstack_name_register( "foo2.test", pk, wallets[2].addr ) # should fail at this point, since the preorder sent to the wrong burn address testlib.blockstack_name_preorder( "foo3.test", pk, wallets[2].addr, price={ 'units': 'STACKS', 'amount': stacks_price }, burn_addr=blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS, safety_checks=False) testlib.blockstack_name_preorder( "bar3.test", pk, wallets[2].addr, price={ 'units': 'STACKS', 'amount': stacks_price - 1 }, burn_addr=blockstack.lib.config.BLOCKSTACK_BURN_ADDRESS, safety_checks=False) testlib.next_block(**kw) testlib.expect_snv_fail_at('bar2.test', testlib.get_current_block(**kw)) testlib.expect_snv_fail_at('foo2.test', testlib.get_current_block(**kw)) # tokens are not yet accepted if testlib.get_state_engine().get_name('bar2.test'): print 'registered bar2.test' return False if testlib.get_state_engine().get_name('foo2.test'): print 'registered foo2.test' return False # preorder/register using Stacks (should succeed without safety checks or overrides) testlib.blockstack_name_preorder("foo.test", pk, wallets[2].addr, price={ 'units': 'STACKS', 'amount': stacks_price }) testlib.next_block(**kw) testlib.blockstack_name_register("foo.test", pk, wallets[2].addr) # should succeed testlib.blockstack_name_register("bar2.test", pk, wallets[2].addr) # should fail testlib.blockstack_name_register("foo2.test", pk, wallets[2].addr) # should succeed testlib.blockstack_name_register("bar3.test", pk, wallets[2].addr) # should fail testlib.blockstack_name_register("foo3.test", pk, wallets[2].addr) # should succeed testlib.next_block(**kw) testlib.expect_snv_fail_at('bar2.test', testlib.get_current_block(**kw)) testlib.expect_snv_fail_at('bar3.test', testlib.get_current_block(**kw)) if testlib.get_state_engine().get_name('bar2.test'): print 'registered bar2.test' return False if testlib.get_state_engine().get_name('bar3.test'): print 'registered bar3.test' return False
def do_POST(self): content_type = self.headers.getheader('content-type') postvars = {} txid = None if content_type is not None: ctype, pdict = cgi.parse_header(content_type) if ctype == 'multipart/form-data': postvars = cgi.parse_multipart(self.rfile, pdict) elif ctype == 'application/x-www-form-urlencoded': length = int(self.headers.getheader('content-length')) postvars = cgi.parse_qs(self.rfile.read(length), keep_blank_values=1) if self.path == '/sendBTC': # fund an address with bitcoin addr = postvars.get('addr', [None]) value = postvars.get('value', [None]) if addr[0] is None or value[0] is None: log.error("Missing addr or value") self.error_page(400, "Invalid request: missing addr or value") return # addr can be either base58check or c32check if re.match('^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]+$', addr[0]): # c32check try: res = testlib.nodejs_cli('convert_address', addr[0]) res = json.loads(res) addr = [res['BTC']] except: self.error_page(500, 'Failed to convert {} to a Stacks address'.format(addr[0])) self.end_headers() return try: value = int(value[0]) addr = virtualchain.address_reencode(addr[0]) except: log.error("Failed to read addr and/or value") log.error("postvars = {}".format(postvars)) self.error_page(400, "Invalid addr or value") return # don't take too much if value > 10000000: log.error('{} requested too much ({})'.format(addr, value)) self.error_page(400, 'Requested too much BTC (at most {} is allowed)'.format(10000000)) return # send funds res = testlib.send_funds(testlib.get_default_payment_wallet().privkey, value, addr) if 'error' in res: log.error("Failed to send {} BTC from {} to {}: {}".format( value, testlib.get_default_payment_wallet().privkey, addr, res )) self.error_page(400, "Failed to send value") return txid = res['txid'] self.send_response(302) location = '/' if txid: location = '/?bitcoinTxid={}'.format(txid) self.send_header('location', location) self.end_headers() return elif self.path == '/sendStacks': # fund an address with bitcoin addr = postvars.get('addr', [None]) value = postvars.get('value', [None]) if addr[0] is None or value[0] is None: log.error("Missing addr or value") log.error("Got {}".format(postvars)) self.error_page(400, "Invalid request: missing addr or value") self.end_headers() return # addr can be either base58check or c32check if re.match('^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]+$', addr[0]): # c32check try: res = testlib.nodejs_cli('convert_address', addr[0]) res = json.loads(res) addr = [res['BTC']] except: self.error_page(500, 'Failed to convert {} to a Stacks address'.format(addr[0])) self.end_headers() return try: value = int(value[0]) addr = virtualchain.address_reencode(str(addr[0])) except: log.error("Failed to read addr and/or value") log.error('addr = {}, value = {}'.format(addr[0], value[0])) self.error_page(400, "Invalid addr or value") self.end_headers() return # don't take too much if value > 1000000000: log.error('{} requested too much ({})'.format(addr, value)) self.error_page(400, 'Requested too much STACKS (at most {} is allowed)'.format(1000000000)) self.end_headers() return # send funds res = None try: res = testlib.blockstack_send_tokens(addr, 'STACKS', value, wallets[3].privkey) txid = res['transaction_hash'] except Exception as e: log.exception(e) self.error_page(500, 'Failed to send tokens to {}\n{}'.format(addr, ''.join(traceback.format_exc()))) self.end_headers() return if 'error' in res: log.error("Failed to send {} Stacks from {} to {}: {}".format( value, testlib.get_default_payment_wallet().privkey, addr, res )) self.error_page(400, "Failed to send value") self.end_headers() return # also send some BTC res = testlib.send_funds(testlib.get_default_payment_wallet().privkey, 5000000, addr) if 'error' in res: log.error("Failed to send {} BTC from {} to {}: {}".format( value, testlib.get_default_payment_wallet().privkey, addr, res )) self.error_page(400, "Failed to send value") return self.send_response(302) location = '/' if txid: location = '/?stacksTxid={}'.format(txid) self.send_header('location', location) self.end_headers() return else: log.error("Unsupported path {}".format(self.path)) self.error_page(400, "Only support /sendfunds at this time") self.end_headers() return
def scenario( wallets, **kw ): # has the side-effect of starting the API server resp = testlib.blockstack_client_initialize_wallet( "0123456789abcdef", wallets[2].privkey, wallets[3].privkey, wallets[4].privkey ) if 'error' in resp: print json.dumps(resp, indent=4, sort_keys=True) return False resp = testlib.blockstack_cli_namespace_preorder("test", wallets[0].privkey, wallets[1].privkey) if 'error' in resp: print json.dumps(resp, indent=4, sort_keys=True) return False testlib.next_block(**kw) resp = testlib.blockstack_cli_namespace_reveal('test', wallets[0].privkey, wallets[1].privkey, 52560, 4, 4, '6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0', 10, 10) if 'error' in resp: print json.dumps(resp, indent=4, sort_keys=True) return False testlib.next_block(**kw) private_keychain = keychain.PrivateKeychain.from_private_key( wallets[1].privkey ) private_keys = [wallets[1].privkey] # NOTE: always start with the reveal key, then use children for i in xrange(0, 4): import_key = private_keychain.child(i).private_key() print "fund {} (child {})".format(import_key, i) res = testlib.send_funds( wallets[1].privkey, 100000000, virtualchain.BitcoinPrivateKey(import_key).public_key().address() ) if 'error' in res: print json.dumps(res, indent=4, sort_keys=True) return False testlib.next_block(**kw) private_keys.append(import_key) # should fail (first key must be revealer) resp = testlib.blockstack_cli_name_import("fail.test", wallets[2].addr, "Hello fail.test!", private_keys[1]) if 'error' not in resp: print json.dumps(resp, indent=4, sort_keys=True) return False # should succeed resp = testlib.blockstack_cli_name_import("foo.test", wallets[2].addr, "Hello foo.test!", private_keys[0]) if 'error' in resp: print json.dumps(resp, indent=4, sort_keys=True) return False testlib.next_block(**kw) # 3 in one block (zero-conf) resp = testlib.blockstack_cli_name_import("bar.test", wallets[3].addr, "Hello bar.test!", private_keys[1]) if 'error' in resp: print json.dumps(resp, indent=4, sort_keys=True) return False resp = testlib.blockstack_cli_name_import("baz.test", wallets[4].addr, "Hello baz.test!", private_keys[2]) if 'error' in resp: print json.dumps(resp, indent=4, sort_keys=True) return False resp = testlib.blockstack_cli_name_import("goo.test", wallets[5].addr, "Hello goo.test!", private_keys[3]) if 'error' in resp: print json.dumps(resp, indent=4, sort_keys=True) return False testlib.next_block(**kw) # should fail (wrong key) resp = testlib.blockstack_cli_name_import("fail.test", wallets[5].addr, "Hello fail.test!", wallets[2].privkey) if 'error' not in resp: print json.dumps(resp, indent=4, sort_keys=True) return False resp = testlib.blockstack_cli_namespace_ready('test', wallets[1].privkey) if 'error' in resp: print json.dumps(resp, indent=4, sort_keys=True) return False for i in xrange(0, 10): testlib.next_block(**kw) print "Waiting 10 seconds for registrar to replicate zone files" time.sleep(10)
def scenario(wallets, **kw): global debug, consensus, small_unspents res = check_utxo_consumption( "test", wallets[0], wallets[1], wallets[2], ['namespace_preorder', 'namespace_reveal', 'namespace_ready'], wallets[1].addr, **kw) if 'error' in res: return False expected_utxo_count = res['expected_utxo_count'] # do the preorder resp = testlib.blockstack_namespace_preorder("test", wallets[1].addr, wallets[0].privkey) if debug or 'error' in resp: print simplejson.dumps(resp, indent=4) testlib.next_block(**kw) # verify that all the small UTXOs are NOT consumed bitcoind = testlib.connect_bitcoind() bitcoind.ping() txdata = bitcoind.getrawtransaction(resp['transaction_hash'], 1) if len(txdata['vin']) != 1: print simplejson.dumps(txdata, indent=4) print "wrong number of inputs: {} != 1".format(len(txdata['vin'])) return False if spent_small_transaction(resp['transaction_hash']): return False # finish ordering the namespace resp = testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10, wallets[0].privkey) if debug or 'error' in resp: print simplejson.dumps(resp, indent=4) if spent_small_transaction(resp['transaction_hash']): return False testlib.next_block(**kw) resp = testlib.blockstack_namespace_ready("test", wallets[1].privkey) if debug or 'error' in resp: print simplejson.dumps(resp, indent=4) if spent_small_transaction(resp['transaction_hash']): return False testlib.next_block(**kw) res = check_utxo_consumption( "foo.test", wallets[2], wallets[3], wallets[4], ['preorder', 'register', 'update', 'transfer'], wallets[4].addr, **kw) if 'error' in res: return False expected_utxo_count = res['expected_utxo_count'] resp = testlib.blockstack_name_preorder("foo.test", wallets[2].privkey, wallets[3].addr) if debug or 'error' in resp: print simplejson.dumps(resp, indent=4) if spent_small_transaction(resp['transaction_hash']): return False testlib.next_block(**kw) # verify that all the small UTXOs are NOT consumed bitcoind = testlib.connect_bitcoind() bitcoind.ping() txdata = bitcoind.getrawtransaction(resp['transaction_hash'], 1) if len(txdata['vin']) != 1: print simplejson.dumps(txdata, indent=4) print "wrong number of inputs: {} != {}".format( len(txdata['vin']), expected_utxo_count) return False # proceed to register resp = testlib.blockstack_name_register("foo.test", wallets[2].privkey, wallets[3].addr) if debug or 'error' in resp: print simplejson.dumps(resp, indent=4) if spent_small_transaction(resp['transaction_hash']): return False testlib.next_block(**kw) # verify that all the UTXOs are consumed bitcoind = testlib.connect_bitcoind() bitcoind.ping() txdata = bitcoind.getrawtransaction(resp['transaction_hash'], 1) if len(txdata['vin']) != 1: print simplejson.dumps(txdata, indent=4) print "wrong number of inputs: {} != {}".format( len(txdata['vin']), expected_utxo_count) return False # make a few small UTXOs for the preorder payment addr for i in xrange(0, 3): res = testlib.send_funds(wallets[1].privkey, 10000, testlib.get_default_payment_wallet().addr) if 'error' in res: print simplejson.dumps(res, indent=4, sort_keys=True) return False testlib.next_block(**kw) small_unspents.append(res['transaction_hash']) utxos = testlib.get_utxos(testlib.get_default_payment_wallet().addr) assert len(utxos) > 3 resp = testlib.blockstack_name_update("foo.test", "11" * 20, wallets[3].privkey) if debug or 'error' in resp: print simplejson.dumps(resp, indent=4) if spent_small_transaction(resp['transaction_hash']): return False consensus = testlib.get_consensus_at(testlib.get_current_block(**kw), **kw) testlib.next_block(**kw) # inspect the transaction: only 3 UTXOs should have been consumed (2 owner UTXOs and 1 payment UTXO) txdata = testlib.connect_bitcoind().getrawtransaction( resp['transaction_hash'], 1) if len(txdata['vin']) != 3: print simplejson.dumps(txdata, indent=4) print "too many inputs" return False # make a few more small UTXOs for the preorder payment addr for i in xrange(0, 3): res = testlib.send_funds(wallets[1].privkey, 10000, testlib.get_default_payment_wallet().addr) if 'error' in res: print simplejson.dumps(res, indent=4, sort_keys=True) return False testlib.next_block(**kw) small_unspents.append(res['transaction_hash']) utxos = testlib.get_utxos(testlib.get_default_payment_wallet().addr) assert len(utxos) > 3 resp = testlib.blockstack_name_transfer("foo.test", wallets[4].addr, True, wallets[3].privkey) if debug or 'error' in resp: print simplejson.dumps(resp, indent=4) # inspect the transaction: only 2 UTXOs should have been consumed (1 owner UTXO and 1 payment UTXO) txdata = testlib.connect_bitcoind().getrawtransaction( resp['transaction_hash'], 1) if len(txdata['vin']) != 2: print simplejson.dumps(txdata, indent=4) print "too many inputs" return False if spent_small_transaction(resp['transaction_hash']): return False testlib.next_block(**kw) # make a few more small UTXOs for the preorder payment addr for i in xrange(0, 3): res = testlib.send_funds(wallets[1].privkey, 10000, testlib.get_default_payment_wallet().addr) if 'error' in res: print simplejson.dumps(res, indent=4, sort_keys=True) return False testlib.next_block(**kw) small_unspents.append(res['transaction_hash']) utxos = testlib.get_utxos(testlib.get_default_payment_wallet().addr) assert len(utxos) > 3 resp = testlib.blockstack_name_renew("foo.test", wallets[4].privkey) if debug or 'error' in resp: print simplejson.dumps(resp, indent=4) # inspect the transaction: only 3 UTXOs should have been consumed (2 owner UTXO and 1 payment UTXO) # NOTE: produces two UTXOs: an "owner" utxo and the change for the owner address txdata = testlib.connect_bitcoind().getrawtransaction( resp['transaction_hash'], 1) if len(txdata['vin']) != 3: print simplejson.dumps(txdata, indent=4) print "too many inputs" return False if spent_small_transaction(resp['transaction_hash']): return False testlib.next_block(**kw) # make a few more small UTXOs for the preorder payment addr for i in xrange(0, 3): res = testlib.send_funds(wallets[1].privkey, 10000, testlib.get_default_payment_wallet().addr) if 'error' in res: print simplejson.dumps(res, indent=4, sort_keys=True) return False testlib.next_block(**kw) small_unspents.append(res['transaction_hash']) utxos = testlib.get_utxos(testlib.get_default_payment_wallet().addr) assert len(utxos) > 3 resp = testlib.blockstack_name_revoke("foo.test", wallets[4].privkey) if debug or 'error' in resp: print simplejson.dumps(resp, indent=4) # inspect the transaction: only 3 UTXOs should have been consumed (2 owner UTXO and 1 payment UTXO) txdata = testlib.connect_bitcoind().getrawtransaction( resp['transaction_hash'], 1) if len(txdata['vin']) != 3: print simplejson.dumps(txdata, indent=4) print "too many inputs" return False if spent_small_transaction(resp['transaction_hash']): return False testlib.next_block(**kw) '''
def scenario(wallets, **kw): # make a test namespace resp = testlib.blockstack_namespace_preorder("test", wallets[1].addr, wallets[0].privkey) if 'error' in resp: print json.dumps(resp, indent=4) return False testlib.next_block(**kw) resp = testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10, wallets[0].privkey) if 'error' in resp: print json.dumps(resp, indent=4) return False testlib.next_block(**kw) # import 3 names in the same block: foo.test, bar.test, baz.test names = ['foo.test', 'bar.test', 'baz.test'] name_preorder_wallets = [wallets[2], wallets[3], wallets[4]] name_register_wallets = [wallets[5], wallets[6], wallets[7]] name_transfer_wallets = [wallets[6], wallets[7], wallets[5]] # derive importer keys and do imports # NOTE: breaks consensus trace from 0.14.0 private_keychain = keychain.PrivateKeychain.from_private_key( wallets[1].privkey) private_keys = [ wallets[1].privkey ] # NOTE: always start with the reveal key, then use children for i in xrange(0, len(names) - 1): import_key = private_keychain.child(i).private_key() print "fund {} (child {})".format(import_key, i) res = testlib.send_funds( wallets[1].privkey, 100000000, virtualchain.BitcoinPrivateKey(import_key).public_key().address()) if 'error' in res: print json.dumps(res, indent=4, sort_keys=True) return False testlib.next_block(**kw) private_keys.append(import_key) for i in xrange(0, len(names)): name = names[i] register_wallet = name_register_wallets[i] import_key = private_keys[i] resp = testlib.blockstack_name_import(name, register_wallet.addr, str(9 - i) * 40, import_key) if 'error' in resp: print json.dumps(resp, indent=4) return False testlib.next_block(**kw) # namespace ready... resp = testlib.blockstack_namespace_ready("test", wallets[1].privkey) if 'error' in resp: print json.dumps(resp, indent=4) return False testlib.next_block(**kw) # update 3 names in the same block for i in xrange(0, len(names)): name = names[i] register_wallet = name_register_wallets[i] resp = testlib.blockstack_name_update(name, str(i + 2) * 40, register_wallet.privkey) if 'error' in resp: print json.dumps(resp, indent=4) return False testlib.next_block(**kw) # update 3 names in the same block, again for i in xrange(0, len(names)): name = names[i] register_wallet = name_register_wallets[i] resp = testlib.blockstack_name_update(name, str(i + 1) * 40, register_wallet.privkey) if 'error' in resp: print json.dumps(resp, indent=4) return False testlib.next_block(**kw) # transfer 3 names in the same block for i in xrange(0, len(names)): name = names[i] register_wallet = name_register_wallets[i] transfer_wallet = name_transfer_wallets[i] resp = testlib.blockstack_name_transfer(name, transfer_wallet.addr, True, register_wallet.privkey) if 'error' in resp: print json.dumps(resp, indent=4) return False testlib.next_block(**kw) # exchange after transfer... tmp = name_register_wallets name_register_wallets = name_transfer_wallets name_transfer_wallets = tmp # revoke 3 names in the same block for i in xrange(0, len(names)): name = names[i] register_wallet = name_register_wallets[i] resp = testlib.blockstack_name_revoke(name, register_wallet.privkey) if 'error' in resp: print json.dumps(resp, indent=4) return False # iterate the blocks a few times for i in xrange(0, 5): testlib.next_block(**kw)
def check_utxo_consumption(name_or_ns, payment_wallet, owner_wallet, data_wallet, operations, recipient_address, **kw): global small_unspents wallet = testlib.blockstack_client_initialize_wallet( "0123456789abcdef", payment_wallet.privkey, owner_wallet.privkey, data_wallet.privkey) test_proxy = testlib.TestAPIProxy() blockstack_client.set_default_proxy(test_proxy) # estimate the fee for the operation sequence fees = testlib.blockstack_cli_price(name_or_ns, "0123456789abcdef", recipient_address=recipient_address, operations=operations) if 'error' in fees: return fees print "without UTXOs:" print simplejson.dumps(fees, indent=4, sort_keys=True) # make a few small UTXOs for the payment address # count up the number of UTXOs that exist for this payment address payment_utxos = testlib.get_utxos(payment_wallet.addr) expected_utxo_count = len(payment_utxos) for i in xrange(0, 1): senders = wallets for sender in senders: if sender.privkey == payment_wallet.privkey: continue res = testlib.send_funds(sender.privkey, 10000, payment_wallet.addr) if 'error' in res: print simplejson.dumps(res, indent=4, sort_keys=True) return res expected_utxo_count += 1 small_unspents.append(res['transaction_hash']) testlib.next_block(**kw) # estimate the fee with all the UTXOs fees_utxos = testlib.blockstack_cli_price( name_or_ns, "0123456789abcdef", recipient_address=recipient_address, operations=operations) if 'error' in fees_utxos: return fees_utxos print "with UTXOs:" print simplejson.dumps(fees_utxos, indent=4, sort_keys=True) # all our operations should have similar fees, regardless of the UTXO set for tx_fee_key in ['{}_tx_fee'.format(op) for op in operations]: fee_diff = abs(fees[tx_fee_key]['satoshis'] - fees_utxos[tx_fee_key]['satoshis']) if fee_diff > 5500: print 'tx fees for {} disagree by {}'.format(tx_fee_key, fee_diff) return {'error': 'No appreciable fee change'} return {'status': True, 'expected_utxo_count': expected_utxo_count}