Skip to content

Commit

Permalink
Merge pull request #37 from dexX7/btc-related-support-sto
Browse files Browse the repository at this point in the history
Finish #18: STO invalidation, fix #35: BTC related funding
  • Loading branch information
msgilligan committed Jan 28, 2015
2 parents 283335a + 6d95fdd commit 65d45ca
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import foundation.omni.BaseRegTestSpec
import foundation.omni.CurrencyID
import foundation.omni.Ecosystem
import foundation.omni.PropertyType
import spock.lang.Ignore
import spock.lang.Shared
import spock.lang.Unroll

Expand Down Expand Up @@ -143,7 +142,6 @@ class MSCSendToOwnersTestPlanSpec extends BaseRegTestSpec {
getbalance_MP(actorAddress, currencyMSC).balance == startMSC
}

@Ignore("https://github.com/msgilligan/bitcoin-spock/issues/35")
def "STO Property ID is 0 - bitcoin"() {
def ecosystem = Ecosystem.TMSC
def propertyType = PropertyType.DIVISIBLE
Expand Down Expand Up @@ -186,13 +184,12 @@ class MSCSendToOwnersTestPlanSpec extends BaseRegTestSpec {
getBitcoinBalance(ownerB) == btcAvailableOwners
}

@Ignore("https://github.com/msgilligan/bitcoin-spock/issues/35")
def "Sender owns all the coins of the STO Property, other addresses had non-zero balances but now zero balances"() {
def ecosystem = Ecosystem.TMSC
def propertyType = PropertyType.DIVISIBLE
def amountSTO = 1.0
def startMSC = 1.0
def expectException = true
def expectException = false
def expectedValidity = false
def currencyMSC = new CurrencyID(ecosystem.longValue())

Expand Down
59 changes: 48 additions & 11 deletions src/main/groovy/foundation/omni/test/TestSupport.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import foundation.omni.MPRegTestParams
import foundation.omni.PropertyType
import foundation.omni.rpc.MastercoinClientDelegate

import static foundation.omni.CurrencyID.*

import java.security.SecureRandom

/**
Expand All @@ -27,18 +25,57 @@ trait TestSupport implements MastercoinClientDelegate {
return accountName
}

def requestBitcoin(Address toAddress, BigDecimal requestedBTC) {
def amountGatheredSoFar = 0.0
def inputs = new ArrayList<Map<String, Object>>()

// Newly mined coins need to mature to be spendable
def minCoinAge = 100

if (blockCount < minCoinAge) {
generateBlocks(minCoinAge - blockCount)
}

while (amountGatheredSoFar < requestedBTC) {
generateBlock()
def blockIndex = blockCount - minCoinAge
def block = client.getBlock(blockIndex)
def blockTxs = block.tx as List<String>
def coinbaseTx = new Sha256Hash(blockTxs.get(0))
def txout = client.getTxOut(coinbaseTx, 0)

// txout is empty, if output was already spent
if (txout.containsKey("value")) {
def amountBTCd = txout.value as Double
amountGatheredSoFar += BigDecimal.valueOf(amountBTCd)
def coinbaseTxid = coinbaseTx.toString()
inputs << ["txid": coinbaseTxid, "vout": 0]
}
}

// Don't care about change, we mine it anyway
def outputs = new HashMap<Address, BigDecimal>()
outputs.put(toAddress, requestedBTC)

def unsignedTxHex = client.createRawTransaction(inputs, outputs)
def signingResult = client.signRawTransaction(unsignedTxHex)

assert signingResult.complete == true

def signedTxHex = signingResult.hex as String
def txid = client.sendRawTransaction(signedTxHex, true)

return txid
}

Address createFundedAddress(BigDecimal requestedBTC, BigDecimal requestedMSC) {
final MPNetworkParameters params = MPRegTestParams.get() // Hardcoded for RegTest for now
Address stepAddress = getNewAddress()
def btcForMSC = (requestedMSC / 100).setScale(8, BigDecimal.ROUND_UP)
def startBTC = requestedBTC + btcForMSC + stdTxFee
startBTC += 5 * stdTxFee // To send BTC, MSC and TMSC to the real receiver

// Generate blocks until we have the requested amount of BTC
while (getBalance() < startBTC) {
generateBlock()
}
Sha256Hash txid = sendToAddress(stepAddress, startBTC)
Sha256Hash txid = requestBitcoin(stepAddress, startBTC)
generateBlock()
def tx = getTransaction(txid)
assert tx.confirmations == 1
Expand All @@ -55,8 +92,8 @@ trait TestSupport implements MastercoinClientDelegate {

// Send to the actual destination
Address fundedAddress = getNewAddress()
send_MP(stepAddress, fundedAddress, MSC, requestedMSC)
send_MP(stepAddress, fundedAddress, TMSC, requestedMSC)
send_MP(stepAddress, fundedAddress, CurrencyID.MSC, requestedMSC)
send_MP(stepAddress, fundedAddress, CurrencyID.TMSC, requestedMSC)
generateBlock()
def remainingBTC = requestedBTC - getBitcoinBalance(fundedAddress)
txid = sendBitcoin(stepAddress, fundedAddress, remainingBTC)
Expand All @@ -66,8 +103,8 @@ trait TestSupport implements MastercoinClientDelegate {

// Verify correct amounts received
btcBalance = getBitcoinBalance(fundedAddress)
BigDecimal mscBalance = getbalance_MP(fundedAddress, MSC).balance
BigDecimal tmscBalance = getbalance_MP(fundedAddress, TMSC).balance
BigDecimal mscBalance = getbalance_MP(fundedAddress, CurrencyID.MSC).balance
BigDecimal tmscBalance = getbalance_MP(fundedAddress, CurrencyID.TMSC).balance

assert btcBalance == requestedBTC
assert mscBalance == requestedMSC
Expand Down
71 changes: 71 additions & 0 deletions src/main/java/com/msgilligan/bitcoin/rpc/BitcoinClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,48 @@ public Integer getBlockCount() throws JsonRPCException, IOException {
return blockCount;
}

/**
* Returns the hash of block in best-block-chain at index provided.
*
* @param index The block index
* @return The block hash
*/
public Sha256Hash getBlockHash(Integer index) throws JsonRPCException, IOException {
List<Object> params = createParamList(index);
Map<String, Object> response = send("getblockhash", params);

String hashStr = (String) response.get("result");
Sha256Hash hash = new Sha256Hash(hashStr);
return hash;
}

/**
* Returns information about a block with the given block hash.
*
* @param hash The block hash
* @return The information about the block
*/
public Map<String,Object> getBlock(Sha256Hash hash) throws JsonRPCException, IOException {
// Use "verbose = true"
List<Object> params = createParamList(hash.toString(), true);
Map<String, Object> response = send("getblock", params);

@SuppressWarnings("unchecked")
Map<String, Object> json = (Map<String, Object>) response.get("result");
return json;
}

/**
* Returns information about a block at index provided.
*
* @param index The block index
* @return The information about the block
*/
public Map<String,Object> getBlock(Integer index) throws JsonRPCException, IOException {
Sha256Hash blockHash = getBlockHash(index);
return getBlock(blockHash);
}

/**
*
* @param generate turn generation on or off
Expand Down Expand Up @@ -366,6 +408,35 @@ public List<Map<String, Object>> listUnspent(Integer minConf, Integer maxConf, I
return unspent;
}

/**
* Returns details about an unspent transaction output.
*
* @param txid The transaction hash
* @param vout The transaction output index
* @return Details about an unspent output or nothing, if the output was already spent
*/
public Map<String,Object> getTxOut(Sha256Hash txid, Integer vout) throws JsonRPCException, IOException {
return getTxOut(txid, vout, null);
}

/**
* Returns details about an unspent transaction output.
*
* @param txid The transaction hash
* @param vout The transaction output index
* @param includeMemoryPool Whether to included the memory pool
* @return Details about an unspent output or nothing, if the output was already spent
*/
public Map<String,Object> getTxOut(Sha256Hash txid, Integer vout, Boolean includeMemoryPool)
throws JsonRPCException, IOException {
List<Object> params = createParamList(txid.toString(), vout, includeMemoryPool);
Map<String, Object> response = send("gettxout", params);

@SuppressWarnings("unchecked")
Map<String, Object> json = (Map<String, Object>) response.get("result");
return json;
}

public BigDecimal getBalance() throws JsonRPCException, IOException {
return getBalance(null, null);
}
Expand Down

0 comments on commit 65d45ca

Please sign in to comment.