def test_TestTransactionPushOutput(): handle = utils.makeEmptyTransaction() a = utils.makeAddress() assert skycoin.SKY_coin_Transaction_PushOutput( handle, a, 100, 150) == skycoin.SKY_OK err, count = skycoin.SKY_coin_Transaction_GetOutputsCount(handle) assert err == skycoin.SKY_OK assert count == 1 pOut1 = skycoin.coin__TransactionOutput() pOut = skycoin.coin__TransactionOutput() pOut1.Address = a pOut1.Coins = 100 pOut1.Hours = 150 assert skycoin.SKY_coin_Transaction_GetOutputAt( handle, 0, pOut) == skycoin.SKY_OK assert pOut == pOut1 for i in range(1, 20): a = utils.makeAddress() assert skycoin.SKY_coin_Transaction_PushOutput( handle, a, int(i * 100), int(i * 50)) == skycoin.SKY_OK err, count = skycoin.SKY_coin_Transaction_GetOutputsCount(handle) assert err == skycoin.SKY_OK assert count == int(i + 1) pOut1.Address = a pOut1.Coins = int(i * 100) pOut1.Hours = int(i * 150) assert skycoin.SKY_coin_Transaction_GetOutputAt( handle, i, pOut) == skycoin.SKY_OK assert pOut == pOut i += 1
def test_TestTransactionSignInputs(): handle = utils.makeEmptyTransaction() # Panics if txns already signed sig = skycoin.cipher_Sig() assert skycoin.SKY_coin_Transaction_PushSignature(handle, sig) == skycoin.SKY_OK secKeys = [] secKeys.append(skycoin.cipher_SecKey()) # Panics if not enough keys handle = utils.makeEmptyTransaction() ux, s = utils.makeUxOutWithSecret() h = skycoin.cipher_SHA256() assert skycoin.SKY_coin_UxOut_Hash(ux, h) == skycoin.SKY_OK err, _ = skycoin.SKY_coin_Transaction_PushInput(handle, h) assert err == skycoin.SKY_OK ux2, s2 = utils.makeUxOutWithSecret() assert skycoin.SKY_coin_UxOut_Hash(ux2, h) == skycoin.SKY_OK err, _ = skycoin.SKY_coin_Transaction_PushInput(handle, h) assert err == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_PushOutput( handle, utils.makeAddress(), 40, 80) == skycoin.SKY_OK err, count = skycoin.SKY_coin_Transaction_GetSignaturesCount(handle) assert err == skycoin.SKY_OK assert count == 0 # Valid signing assert skycoin.SKY_coin_Transaction_HashInner(handle, h) == skycoin.SKY_OK secKeys = [] secKeys.append(s) secKeys.append(s2) assert skycoin.SKY_coin_Transaction_SignInputs( handle, secKeys) == skycoin.SKY_OK err, count = skycoin.SKY_coin_Transaction_GetSignaturesCount(handle) assert err == skycoin.SKY_OK assert count == 2 h2 = skycoin.cipher_SHA256() assert skycoin.SKY_coin_Transaction_HashInner( handle, h2) == skycoin.SKY_OK assert h == h2 p = skycoin.cipher_PubKey() assert skycoin.SKY_cipher_PubKeyFromSecKey(s, p) == skycoin.SKY_OK a = skycoin.cipher__Address() a2 = skycoin.cipher__Address() assert skycoin.SKY_cipher_AddressFromPubKey(p, a) == skycoin.SKY_OK assert skycoin.SKY_cipher_PubKeyFromSecKey(s2, p) == skycoin.SKY_OK assert skycoin.SKY_cipher_AddressFromPubKey(p, a2) == skycoin.SKY_OK sha1 = skycoin.cipher_SHA256() sha2 = skycoin.cipher_SHA256() txin0 = skycoin.cipher_SHA256() txin1 = skycoin.cipher_SHA256() assert skycoin.SKY_coin_Transaction_GetInputAt( handle, 0, txin0) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_GetInputAt( handle, 1, txin1) == skycoin.SKY_OK assert skycoin.SKY_cipher_AddSHA256(h, txin0, sha1) == skycoin.SKY_OK assert skycoin.SKY_cipher_AddSHA256(h, txin1, sha2) == skycoin.SKY_OK txsig0 = skycoin.cipher_Sig() txsig1 = skycoin.cipher_Sig() assert skycoin.SKY_coin_Transaction_GetSignatureAt( handle, 0, txsig0) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_GetSignatureAt( handle, 1, txsig1) == skycoin.SKY_OK
def test_TestCreateUnspent(): err, pubkey, seckey, address = utils.makeKeysAndAddress() assert err == skycoin.SKY_OK hash1 = skycoin.cipher_SHA256() handle = utils.makeEmptyTransaction() err = skycoin.SKY_coin_Transaction_PushOutput(handle, address, 11000000, 255) assert err == skycoin.SKY_OK bh = skycoin.coin__BlockHeader() bh.Time = 0 bh.BkSeq = 1 t = [] tc1 = testcase() t.append(tc1) tc2 = testcase() tc2.index = 10 tc2.failure = skycoin.SKY_ERROR t.append(tc2) ux = skycoin.coin__UxOut() tests_count = len(t) for i in range(tests_count): err = skycoin.SKY_coin_CreateUnspent(bh, handle, t[i].index, ux) if t[i].failure == skycoin.SKY_ERROR: pass assert bh.Time == ux.Head.Time assert bh.BkSeq == ux.Head.BkSeq
def test_TestTransactionOutputHours(): handle = utils.makeEmptyTransaction() assert skycoin.SKY_coin_Transaction_PushOutput( handle, utils.makeAddress(), int(1e6), 100) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_PushOutput( handle, utils.makeAddress(), int(1e6), 200) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_PushOutput( handle, utils.makeAddress(), int(1e6), 500) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_PushOutput( handle, utils.makeAddress(), int(1e6), 0) == skycoin.SKY_OK err, hours = skycoin.SKY_coin_Transaction_OutputHours(handle) assert err == skycoin.SKY_OK assert hours == 800 assert skycoin.SKY_coin_Transaction_PushOutput( handle, utils.makeAddress(), int(1e6), int(utils.MaxUint64 - 700)) == skycoin.SKY_OK err, _ = skycoin.SKY_coin_Transaction_OutputHours(handle) assert err == skycoin.SKY_ERROR
def makeTransactionFromUxOut(ux, s): _, handle = skycoin.SKY_coin_Create_Transaction() _, tx = skycoin.SKY_coin_GetTransactionObject(handle) h = skycoin.cipher_SHA256() assert skycoin.SKY_cipher_SecKey_Verify(s) == skycoin.SKY_OK assert skycoin.SKY_coin_UxOut_Hash(ux, h) == skycoin.SKY_OK r = skycoin.SKY_coin_Transaction_PushInput(handle, h) assert skycoin.SKY_coin_Transaction_PushOutput(handle, makeAddress(), int(1e6), int(50)) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_PushOutput(handle, makeAddress(), int(5e6), int(50)) == skycoin.SKY_OK secKeys = [] secKeys.append(s) assert skycoin.SKY_coin_Transaction_SignInputs(handle, secKeys) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_UpdateHeader(handle) == skycoin.SKY_OK return handle, tx
def test_TestCreateUnspents(): err, pubkey, seckey, address = utils.makeKeysAndAddress() assert err == skycoin.SKY_OK hash1 = skycoin.cipher_SHA256() txn = utils.makeEmptyTransaction() err = skycoin.SKY_coin_Transaction_PushOutput(txn, address, int(11e6), int(255)) assert err == skycoin.SKY_OK bh = skycoin.coin__BlockHeader() bh.Time = 0 bh.BkSeq = 1 err, uxouts = skycoin.SKY_coin_CreateUnspents(bh, txn) assert err == skycoin.SKY_OK assert err == skycoin.SKY_OK assert len(uxouts) == 1
def test_TestTransactionFee(): addr = utils.makeAddress() for j in range(len(cases)): tc = cases[j] tx = utils.makeEmptyTransaction() for h in tc.out: err = skycoin.SKY_coin_Transaction_PushOutput(tx, addr, 0, h) assert err == skycoin.SKY_OK inUxs = utils.makeUxArray(len(tc.ins)) for i in range(len(tc.ins)): b = tc.ins[i] inUxs[i].Head.Time = b.time inUxs[i].Body.Coins = int(b.coins) inUxs[i].Body.Hours = int(b.hours) err, fee = skycoin.SKY_fee_TransactionFee(tx, int(tc.headTime), inUxs) assert err == tc.err assert tc.fee == fee
def test_TestTransactionVerify(): # Mismatch header hash handle, tx = utils.makeTransaction() h = skycoin.cipher_SHA256() h.assignTo(tx.InnerHash) assert skycoin.SKY_coin_Transaction_Verify(handle) == skycoin.SKY_ERROR # No inputs handle, tx = utils.makeTransaction() assert skycoin.SKY_coin_Transaction_ResetInputs( handle, 0) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_UpdateHeader(handle) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_Verify(handle) == skycoin.SKY_ERROR # No outputs handle, _ = utils.makeTransaction() assert skycoin.SKY_coin_Transaction_ResetOutputs( handle, 0) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_UpdateHeader(handle) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_Verify(handle) == skycoin.SKY_ERROR # Invalid number of Sigs handle, _ = utils.makeTransaction() assert skycoin.SKY_coin_Transaction_ResetSignatures( handle, 0) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_UpdateHeader(handle) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_Verify(handle) == skycoin.SKY_ERROR assert skycoin.SKY_coin_Transaction_ResetSignatures( handle, 20) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_UpdateHeader(handle) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_Verify(handle) == skycoin.SKY_ERROR # Too many sigs & inputs handle, _ = utils.makeTransaction() assert skycoin.SKY_coin_Transaction_ResetSignatures( handle, utils.MaxUint16) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_ResetInputs( handle, utils.MaxUint16) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_UpdateHeader(handle) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_Verify(handle) == skycoin.SKY_ERROR # Duplicate inputs ux, s = utils.makeUxOutWithSecret() handle, _ = utils.makeTransactionFromUxOut(ux, s) h = skycoin.cipher_SHA256() assert skycoin.SKY_coin_Transaction_GetInputAt( handle, 0, h) == skycoin.SKY_OK err, _ = skycoin.SKY_coin_Transaction_PushInput(handle, h) assert err == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_ResetSignatures( handle, 0) == skycoin.SKY_OK secKeys = [] secKeys.append(s) secKeys.append(s) assert skycoin.SKY_coin_Transaction_SignInputs( handle, secKeys) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_UpdateHeader(handle) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_Verify(handle) == skycoin.SKY_ERROR # Duplicate outputs handle, _ = utils.makeTransaction() pOutput = skycoin.coin__TransactionOutput() assert skycoin.SKY_coin_Transaction_GetOutputAt( handle, 0, pOutput) == skycoin.SKY_OK pOutput.Address = skycoin.cipher__Address() assert skycoin.SKY_coin_Transaction_ResetOutputs( handle, 0) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_PushOutput( handle, pOutput.Address, pOutput.Coins, pOutput.Hours) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_PushOutput( handle, pOutput.Address, pOutput.Coins, pOutput.Hours) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_UpdateHeader(handle) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_Verify(handle) == skycoin.SKY_ERROR # Output coins are 0 handle, _ = utils.makeTransaction() assert skycoin.SKY_coin_Transaction_GetOutputAt( handle, 0, pOutput) == skycoin.SKY_OK pOutput.Coins = 0 assert skycoin.SKY_coin_Transaction_ResetOutputs( handle, 0) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_PushOutput( handle, pOutput.Address, pOutput.Coins, pOutput.Hours) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_UpdateHeader(handle) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_Verify(handle) == skycoin.SKY_ERROR # Output coin overflow handle, _ = utils.makeTransaction() assert skycoin.SKY_coin_Transaction_GetOutputAt( handle, 0, pOutput) == skycoin.SKY_OK pOutput.Coins = int(utils.MaxUint64 - int(3e6)) assert skycoin.SKY_coin_Transaction_PushOutput( handle, pOutput.Address, pOutput.Coins, pOutput.Hours) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_UpdateHeader(handle) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_Verify(handle) == skycoin.SKY_ERROR # Output coins are not multiples of 1e6 (valid, decimal restriction is not # enforced here) handle, _ = utils.makeTransaction() assert skycoin.SKY_coin_Transaction_GetOutputAt( handle, 0, pOutput) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_ResetOutputs( handle, 0) == skycoin.SKY_OK pOutput.Coins += 10 assert skycoin.SKY_coin_Transaction_PushOutput( handle, pOutput.Address, pOutput.Coins, pOutput.Hours) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_UpdateHeader(handle) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_ResetSignatures( handle, 0) == skycoin.SKY_OK p = skycoin.cipher_PubKey() s = skycoin.cipher_SecKey() assert skycoin.SKY_cipher_GenerateKeyPair(p, s) == skycoin.SKY_OK secKeys = [] secKeys.append(s) assert skycoin.SKY_coin_Transaction_SignInputs( handle, secKeys) == skycoin.SKY_OK assert int(pOutput.Coins % int(1e6)) != int(0) assert skycoin.SKY_coin_Transaction_Verify(handle) == skycoin.SKY_OK # Valid handle, _ = utils.makeTransaction() assert skycoin.SKY_coin_Transaction_GetOutputAt( handle, 0, pOutput) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_ResetOutputs( handle, 0) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_PushOutput( handle, pOutput.Address, int(10e6), pOutput.Hours) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_PushOutput( handle, pOutput.Address, int(1e6), pOutput.Hours) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_UpdateHeader(handle) == skycoin.SKY_OK assert skycoin.SKY_coin_Transaction_Verify(handle) == skycoin.SKY_OK
def test_TestVerifyTransactionFee(): addr = utils.makeAddress() emptyTxn = utils.makeEmptyTransaction() err, hours = skycoin.SKY_coin_Transaction_OutputHours(emptyTxn) assert err == skycoin.SKY_OK assert 0 == hours # A txn with no outputs hours and no coinhours burn fee is valid err = skycoin.SKY_fee_VerifyTransactionFee(emptyTxn, 0, 2) assert err == skycoin.SKY_ErrTxnNoFee # A txn with no outputs hours but with a coinhours burn fee is valid err = skycoin.SKY_fee_VerifyTransactionFee(emptyTxn, 100, 2) assert err == skycoin.SKY_OK txn = utils.makeEmptyTransaction() addr = utils.makeAddress() err = skycoin.SKY_coin_Transaction_PushOutput(txn, addr , 0, int(1e6)) assert err == skycoin.SKY_OK err = skycoin.SKY_coin_Transaction_PushOutput(txn, addr , 0, int(3e6)) assert err == skycoin.SKY_OK err , hours = skycoin.SKY_coin_Transaction_OutputHours(txn) assert err == skycoin.SKY_OK assert hours == int(4e6) # A txn with insufficient net coinhours burn fee is invalid err = skycoin.SKY_fee_VerifyTransactionFee(txn, 0, 2) assert err == skycoin.SKY_ErrTxnNoFee err = skycoin.SKY_fee_VerifyTransactionFee(txn, 1, 2) assert err == skycoin.SKY_ErrTxnInsufficientFee # A txn with sufficient net coinhours burn fee is valid err, hours = skycoin.SKY_coin_Transaction_OutputHours(txn) assert err == skycoin.SKY_OK err = skycoin.SKY_fee_VerifyTransactionFee(txn, hours, 2) assert err == skycoin.SKY_OK err, hours = skycoin.SKY_coin_Transaction_OutputHours(txn) assert err == skycoin.SKY_OK err = skycoin.SKY_fee_VerifyTransactionFee(txn, hours * 10, 2) assert err == skycoin.SKY_OK # fee + hours overflows err = skycoin.SKY_fee_VerifyTransactionFee(txn, utils.MaxUint64 - int(3e6), 2) assert err == skycoin.SKY_ERROR # txn has overflowing output hours err = skycoin.SKY_coin_Transaction_PushOutput(txn, addr, 0, int(utils.MaxUint64 - 1e6 - 3e6 + 1)) assert err == skycoin.SKY_OK err = skycoin.SKY_fee_VerifyTransactionFee(txn, 10, 2) assert err == skycoin.SKY_ERROR cases = burnFactor2verifyTxFeeTestCase for tc in cases: txn = utils.makeEmptyTransaction() err = skycoin.SKY_coin_Transaction_PushOutput(txn, addr, 0, tc.outputHours) assert tc.inputHours >= tc.outputHours err = skycoin.SKY_fee_VerifyTransactionFee(txn, int(tc.inputHours - tc.outputHours), 2) assert tc.err == err
def test_TestTransactionFee(): headTime = int(1000) nextTime = int(headTime + 3600) # 1 hour later cases = [] # Test case with one output, one input case1 = tmpstruct() case1.fee = 5 case1.headTime = 1000 case1.out = [5] case1.ins.append(uxInput(headTime, 10e6, 10)) cases.append(case1) # Test case with multiple outputs, multiple inputs case2 = tmpstruct() case2.fee = 0 case2.headTime = 1000 case2.out = [5, 7, 3] case2.ins.append(uxInput(headTime, int(10e6), 10)) case2.ins.append(uxInput(headTime, int(10e6), 5)) cases.append(case2) # # Test case with multiple outputs, multiple inputs, and some inputs have more CoinHours once adjusted for HeadTime case3 = tmpstruct() case3.fee = 8 case3.headTime = 1000 case3.out.append(5) case3.out.append(10) case3.ins.append(uxInput(nextTime, 10e6, 10)) case3.ins.append(uxInput(nextTime, 8e6, 5)) # Test case with insufficient coin hours case4 = tmpstruct() case4.err = skycoin.SKY_ErrTxnInsufficientCoinHours case4.out.append(5) case4.out.append(10) case4.out.append(1) case4.ins.append(uxInput(headTime, 10e6, 10)) case4.ins.append(uxInput(headTime, 8e6, 5)) # Test case with overflowing input hours case5 = tmpstruct() case5.err = skycoin.SKY_ERROR case5.out.append(0) case5.ins.append(uxInput(headTime, 10e6, 10)) case5.ins.append(uxInput(headTime, 10e6, utils.MaxUint64 - 9)) case5.headTime = 1000 # Test case with overflowing output hours case6 = tmpstruct() case6.err = skycoin.SKY_ERROR case6.out.append(0) case6.out.append(10) case6.out.append(utils.MaxUint64 - 9) case6.ins.append(uxInput(headTime, 10e6, 10)) case6.ins.append(uxInput(headTime, 10e6, 100)) case6.headTime = 1000 addr = utils.makeAddress() for j in range(len(cases)): tc = cases[j] tx = utils.makeEmptyTransaction() for h in tc.out: err = skycoin.SKY_coin_Transaction_PushOutput(tx, addr, 0, h) assert err == skycoin.SKY_OK inUxs = utils.makeUxArray(len(tc.ins)) for i in range(len(tc.ins)): b = tc.ins[i] inUxs[i].Head.Time = b.time inUxs[i].Body.Coins = int(b.coins) inUxs[i].Body.Hours = int(b.hours) err, fee = skycoin.SKY_fee_TransactionFee(tx, int(tc.headTime), inUxs) assert err == tc.err assert tc.fee == fee