public void TestAddInputsWithSecurityLevelHigherThanOneShouldAddMultipleTransactionsToHoldSignature() { var bundle = new Bundle(); bundle.AddTransaction( new Address("TESTVALUE9DONTUSEINPRODUCTION99999VELDTFQHDFTHIHFE9II9WFFDFHEATEI99GEDC9BAUH9EBGZ") { Balance = 84 }, new TryteString(), Tag.Empty, 999999999L); bundle.AddInput( new List <Address> { new Address("NVGLHFZWLEQAWBDJXCWJBMVBVNXEG9DALNBTAYMKEMMJ9BCDVVHJJLSTQW9JEJXUUX9JNFGALBNASRDUD") { Balance = 42, KeyIndex = 4, SecurityLevel = 2 }, new Address("XXYRPQ9BDZGKZZQLYNSBDD9HZLI9OFRK9TZCTU9PFAJYXZIZGO9BWLOCNGVMTLFQFMGJWYRMLXSCW9UTQ") { Balance = 42, KeyIndex = 5, SecurityLevel = 3 } }); bundle.Finalize(); Assert.AreEqual(6, bundle.Transactions.Count); }
/// <inheritdoc /> public async Task <Bundle> PrepareTransferAsync(Seed seed, Bundle bundle, int securityLevel, Address remainderAddress = null, List <Address> inputAddresses = null) { // user wants to spend IOTA, so we need to find input addresses (if not provided) with valid balances if (bundle.Balance > 0) { inputAddresses = inputAddresses == null ? (await this.GetInputsAsync(seed, bundle.Balance, securityLevel, 0)).Addresses : (await this.GetBalancesAsync(inputAddresses)).Addresses; var availableAmount = inputAddresses.Sum(a => a.Balance); if (availableAmount < bundle.Balance) { throw new IotaApiException($"Insufficient balance! Found {availableAmount}. Need {bundle.Balance}"); } bundle.AddInput(inputAddresses); } // the bundle balance currently spends less iota tokens than available. that means we have to send remaining funds to a remainder address in order to prevent key reuse if (bundle.Balance < 0) { if (remainderAddress == null) { remainderAddress = (await this.GetNewAddressesAsync(seed, 0, 1, securityLevel))[0]; } bundle.AddRemainder(remainderAddress); } bundle.Finalize(); bundle.Sign(); return(bundle); }
public void TestBundleHasInsufficientInputsShouldNotBeFinalizable() { var transfer = new Transfer { Address = new Address("RBTC9D9DCDEAUCFDCDADEAMBHAFAHKAJDHAODHADHDAD9KAHAJDADHJSGDJHSDGSDPODHAUDUAHDJAHAB") { Balance = 42 }, Message = new TryteString(), Tag = Tag.Empty }; var bundle = new Bundle(); bundle.AddTransaction(transfer.Address, transfer.Message, transfer.Tag, 999999999L); bundle.AddInput( new List <Address> { new Address("NVGLHFZWLEQAWBDJXCWJBMVBVNXEG9DALNBTAYMKEMMJ9BCDVVHJJLSTQW9JEJXUUX9JNFGALBNASRDUD") { Balance = 40, KeyIndex = 0, SecurityLevel = 1 } }); Assert.AreEqual(2, bundle.Balance); bundle.Finalize(); }
public void TestBundleIsFinalizedShouldThrowExceptionOnAddInput() { var bundle = new Bundle(); bundle.AddTransaction( new Address("TESTVALUE9DONTUSEINPRODUCTION99999VELDTFQHDFTHIHFE9II9WFFDFHEATEI99GEDC9BAUH9EBGZ") { Balance = 84 }, new TryteString(), Tag.Empty, 999999999L); bundle.Finalize(); bundle.AddInput( new List <Address> { new Address("NVGLHFZWLEQAWBDJXCWJBMVBVNXEG9DALNBTAYMKEMMJ9BCDVVHJJLSTQW9JEJXUUX9JNFGALBNASRDUD") { Balance = 42, KeyIndex = 4, SecurityLevel = 2 } }); }
public void TestAddInputsCoversTheExactAmountSpentShouldCreateCorrectTransactionCount() { var bundle = new Bundle(); bundle.AddTransaction( new Address("TESTVALUE9DONTUSEINPRODUCTION99999VELDTFQHDFTHIHFE9II9WFFDFHEATEI99GEDC9BAUH9EBGZ") { Balance = 29 }, new TryteString(), Tag.Empty, 999999999L); bundle.AddTransaction( new Address("TESTVALUE9DONTUSEINPRODUCTION99999OGVEEFBCYAM9ZEAADBGBHH9BPBOHFEGCFAM9DESCCHODZ9Y") { Balance = 13 }, new TryteString(), Tag.Empty, 999999999L); bundle.AddInput( new List <Address> { new Address("KHWHSTISMVVSDCOMHVFIFCTINWZT9EHJUATYSMCXDSMZXPL9KXREBBYHJGRBCYVGPJQEHEDPXLBDJNQNX") { Balance = 40, KeyIndex = 1, SecurityLevel = 1 }, new Address("GOAAMRU9EALPO9GKBOWUVZVQEJMB9CSGIZJATHRBTRRJPNTSQRZTASRBTQCRFAIDOGTWSHIDGOUUULQIG") { Balance = 2, KeyIndex = 2, SecurityLevel = 1 } }); // since balance and spent tokens are even, this should be ignored bundle.AddRemainder(new Address("TESTVALUE9DONTUSEINPRODUCTION99999KAFGVCIBLHS9JBZCEFDELEGFDCZGIEGCPFEIQEYGA9UFPAE")); bundle.Finalize(); Assert.AreEqual(4, bundle.Transactions.Count); }
public void TestBundleIsFinalizedShouldApplySigningFragmentAndWithExtraTransactionsForSecurityLevelAboveOne() { var bundle = new Bundle(); bundle.AddTransaction( new Address("TESTVALUE9DONTUSEINPRODUCTION99999VELDTFQHDFTHIHFE9II9WFFDFHEATEI99GEDC9BAUH9EBGZ") { Balance = 42 }, new TryteString("ASDF"), Tag.Empty, 999999999L); bundle.AddInput( new List <Address> { new Address("KHWHSTISMVVSDCOMHVFIFCTINWZT9EHJUATYSMCXDSMZXPL9KXREBBYHJGRBCYVGPJQEHEDPXLBDJNQNX") { Balance = 40, KeyIndex = 1, SecurityLevel = 2 }, new Address("GOAAMRU9EALPO9GKBOWUVZVQEJMB9CSGIZJATHRBTRRJPNTSQRZTASRBTQCRFAIDOGTWSHIDGOUUULQIG") { Balance = 2, KeyIndex = 2, SecurityLevel = 3 } }); bundle.Finalize(); bundle.Sign(new KeyGeneratorStub()); Assert.AreEqual(6, bundle.Transactions.Count); Assert.IsTrue(string.IsNullOrEmpty(bundle.Transactions[0].SignatureFragment)); for (var i = 1; i < bundle.Transactions.Count; i++) { Assert.IsTrue(!string.IsNullOrEmpty(bundle.Transactions[i].SignatureFragment)); } }
public void TestBundleHasUnspentInputsButRemainderIsGivenShouldBeFinalizable() { var transfer = new Transfer { Address = new Address("RBTC9D9DCDEAUCFDCDADEAMBHAFAHKAJDHAODHADHDAD9KAHAJDADHJSGDJHSDGSDPODHAUDUAHDJAHAB") { Balance = 42 }, Message = new TryteString(), Tag = Tag.Empty }; var bundle = new Bundle(); bundle.AddTransaction(transfer.Address, transfer.Message, transfer.Tag, 999999999L); bundle.AddInput( new List <Address> { new Address("NVGLHFZWLEQAWBDJXCWJBMVBVNXEG9DALNBTAYMKEMMJ9BCDVVHJJLSTQW9JEJXUUX9JNFGALBNASRDUD") { Balance = 42, KeyIndex = 0, SecurityLevel = 1 }, new Address("XXYRPQ9BDZGKZZQLYNSBDD9HZLI9OFRK9TZCTU9PFAJYXZIZGO9BWLOCNGVMTLFQFMGJWYRMLXSCW9UTQ") { Balance = 2, KeyIndex = 2, SecurityLevel = 1 } }); bundle.AddRemainder(new Address("NVGLHFZWLEQAWBDJXCWJBMVBVNXEG9DALNBTAYMKEMMJ9BCDVVHJJLSTQW9JEJXUUX9JNFGALBNASRDUD")); bundle.Finalize(); Assert.AreEqual(0, bundle.Balance); Assert.AreEqual(4, bundle.Transactions.Count); }