Skip to content

Commit c6986bf

Browse files
thibault-martinezCylix
authored andcommitted
Bundle finalization (#261)
* Repeat finalization until normalized bundle hash contains no 13 * Fix finalization of empty bundles * Fix bundle finalization test * Include <algorithm>
1 parent f7581a0 commit c6986bf

File tree

4 files changed

+68
-101
lines changed

4 files changed

+68
-101
lines changed

include/iota/types/trinary.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,13 @@ tritsToInt(const Trits& trits) {
149149
return res;
150150
}
151151

152+
/**
153+
* Increments the specified trits.
154+
*
155+
* @param trits The trits.
156+
*/
157+
void incrementTrits(Trits& trits);
158+
152159
} // namespace Types
153160

154161
} // namespace IOTA

source/models/bundle.cpp

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
//
2424
//
2525

26+
#include <algorithm>
27+
2628
#include <iota/constants.hpp>
2729
#include <iota/crypto/kerl.hpp>
2830
#include <iota/models/bundle.hpp>
@@ -90,33 +92,46 @@ Bundle::addTransaction(const Transaction& transaction, int32_t signatureMessageL
9092
void
9193
Bundle::finalize() {
9294
Crypto::Kerl k;
95+
bool validBundle = false;
96+
97+
while (!validBundle) {
98+
k.reset();
99+
for (std::size_t i = 0; i < transactions_.size(); i++) {
100+
auto& trx = transactions_[i];
101+
102+
trx.setCurrentIndex(i);
103+
trx.setLastIndex(transactions_.size() - 1);
104+
105+
auto value = Types::tritsToTrytes(Types::intToTrits(trx.getValue(), SeedLength));
106+
auto timestamp =
107+
Types::tritsToTrytes(Types::intToTrits(trx.getTimestamp(), TryteAlphabetLength));
108+
auto currentIndex =
109+
Types::tritsToTrytes(Types::intToTrits(trx.getCurrentIndex(), TryteAlphabetLength));
110+
auto lastIndexTrits =
111+
Types::tritsToTrytes(Types::intToTrits(trx.getLastIndex(), TryteAlphabetLength));
112+
113+
auto bytes = Types::trytesToBytes(trx.getAddress().toTrytes() + value +
114+
trx.getObsoleteTag().toTrytesWithPadding() + timestamp +
115+
currentIndex + lastIndexTrits);
116+
k.absorb(bytes);
117+
}
93118

94-
for (std::size_t i = 0; i < transactions_.size(); i++) {
95-
auto& trx = transactions_[i];
96-
97-
trx.setCurrentIndex(i);
98-
trx.setLastIndex(transactions_.size() - 1);
99-
100-
auto value = Types::tritsToTrytes(Types::intToTrits(trx.getValue(), SeedLength));
101-
auto timestamp =
102-
Types::tritsToTrytes(Types::intToTrits(trx.getTimestamp(), TryteAlphabetLength));
103-
auto currentIndex =
104-
Types::tritsToTrytes(Types::intToTrits(trx.getCurrentIndex(), TryteAlphabetLength));
105-
auto lastIndexTrits =
106-
Types::tritsToTrytes(Types::intToTrits(trx.getLastIndex(), TryteAlphabetLength));
107-
108-
auto bytes = Types::trytesToBytes(trx.getAddress().toTrytes() + value +
109-
trx.getTag().toTrytesWithPadding() + timestamp +
110-
currentIndex + lastIndexTrits);
111-
112-
k.absorb(bytes);
119+
std::vector<uint8_t> hash(ByteHashLength);
120+
k.finalSqueeze(hash);
121+
122+
//! set bundle hash for each underlying transaction
123+
hash_ = Types::bytesToTrytes(hash);
124+
auto normalizedHash = normalizedBundle(hash_);
125+
if (transactions_.size() != 0 && std::find(std::begin(normalizedHash), std::end(normalizedHash),
126+
13 /* = M */) != std::end(normalizedHash)) {
127+
// Insecure bundle. Increment Tag and recompute bundle hash.
128+
auto tagTrits = Types::trytesToTrits(transactions_[0].getObsoleteTag().toTrytesWithPadding());
129+
Types::incrementTrits(tagTrits);
130+
transactions_[0].setObsoleteTag(Types::tritsToTrytes(tagTrits));
131+
} else {
132+
validBundle = true;
133+
}
113134
}
114-
115-
std::vector<uint8_t> hash(ByteHashLength);
116-
k.finalSqueeze(hash);
117-
118-
//! set bundle hash for each underlying transaction
119-
hash_ = Types::bytesToTrytes(hash);
120135
for (std::size_t i = 0; i < transactions_.size(); i++) {
121136
transactions_[i].setBundle(hash_);
122137
}

source/types/trinary.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,14 +187,14 @@ tritsToTrytes(const Trits& trits, std::size_t length) {
187187
return trytes;
188188
}
189189

190-
Types::Trits
190+
Trits
191191
intToTrits(const int64_t& value) {
192192
if (value == 0)
193193
return {};
194194

195-
Types::Trits trits;
196-
int sign = (value > 0) - (value < 0);
197-
uint64_t absoluteValue = value * sign;
195+
Trits trits;
196+
int sign = (value > 0) - (value < 0);
197+
uint64_t absoluteValue = value * sign;
198198

199199
// pre-computed log3(e)
200200
static const double log3e = 0.91023922662683739361;
@@ -217,7 +217,7 @@ intToTrits(const int64_t& value) {
217217
return trits;
218218
}
219219

220-
Types::Trits
220+
Trits
221221
intToTrits(const int64_t& value, std::size_t length) {
222222
auto res = intToTrits(value);
223223

@@ -226,6 +226,17 @@ intToTrits(const int64_t& value, std::size_t length) {
226226
return res;
227227
}
228228

229+
void
230+
incrementTrits(Trits& trits) {
231+
for (unsigned int i = 0; i < trits.size(); ++i) {
232+
if (++trits[i] > 1) {
233+
trits[i] = -1;
234+
} else {
235+
break;
236+
}
237+
}
238+
}
239+
229240
} // namespace Types
230241

231242
} // namespace IOTA

test/source/models/bundle_test.cpp

Lines changed: 5 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -219,81 +219,15 @@ TEST(Bundle, GtOperator) {
219219
TEST(Bundle, Finalize) {
220220
IOTA::Models::Bundle b;
221221

222-
b.addTransaction(
223-
{ "RGGVEMTBJIZEES9AWZTCMIQPAKJZ9JYDZBZCWCUGQPFMHCMAUXNFRSHLIKELNPUYTIPMJQKDJQVORVHWWBFZQRYWGZ"
224-
"OVVRBJPOFDDJKHICAFQEWZH9XGLYZGPYNHOQMGCIOP9GLUTHPCEZHWRYAPOYLKRZLSAMXNLCAWSMCVBTJOUBPDJXZL"
225-
"MQKRW9HHTFOOFHZKE9SNXBNPLKNWXABPZFOSPDCZPXVHQRXYFWSUAGLIVJJQABUWKNZWPURHNQMVXBMWYWXKJBOWBD"
226-
"KHFMQNBSI9JWMMBRFAJJPGIVMOELGT9EPYLSODUMLCNWBIDWSRHVDFLYAPORAUUOESG9JTFXFDRFVIZMNUJFIKSJTR"
227-
"QRMTBTYKK9DGEGSZMVNRNBLWXJJUZHEHK9GNVSXEATUAOOBSTGKEVLGZBNROMZOUDVBEJYFCIDOCQMNJPIXMVFEB9O"
228-
"SYJGNNJACNQEFS9LITZENJUEFUMMONVPPLVOPISNIZNOILKTU9SGMWKBZLQVERKFAMJEOQQOTAVSJMTLY9JSWKFPFI"
229-
"HMRWMWZ9OWJKNKIIVGEMHAMLTQPRE9UQKZIPT9VXJTN9CGUGGNRBGNOVYBX9QPCHR9LNLIGSWREHDPNWAQP9TEOEKP"
230-
"ICMPDJQZCGPNSQERKOQJUJJDEQCQILQOOKFHJNDUJMDYZWLDTLUTYWHDLGGPHUVMOAJZRXWGXONTDEMIYVRCBJVDXH"
231-
"TGF9LRWHDDOHEVGQLWPXLPXMCYOZQBSFLNOEHBUORDUSBFYJPCLFSRKOTNMEUQCMYKHHRBJFNNWA9TSRXLPVYIAJOL"
232-
"PKAKIAJYXYSIUKYMEYTZXTBIUJBXEHIOBHANMNDYBCDSBQQSBYKAIEU9OXMIYRGGRXYYEGXB99STNHOQDPK9MCMZBL"
233-
"ZEMKCFOSOTVNULCHGTCIFTFFLXACQPUVPH9ADV9GUZZTPBJJYVUHKDLUUSAHWNZNGTRRUIAUKNHNIBNZRXBFRFEVNL"
234-
"KUYDUQUCKXOTVYTHCLGVGPTWX9ZHOSGEYLNGNOJUQPSDI9KNEYWIOSJPVTZMIK9FUUKRSYFQZJCZVWBACAWRCZZBCV"
235-
"CXQANNFHNIFZACTRBTIOHWTNTTFCACGDSMGZFDCBRYCYOMZXTKOCWATJRPRCIAWWHQIIOPLTTKISZXQJDYSCVEZCWG"
236-
"GXKKEBJAIHXPOYYCARKBSWMMKHVSXPHGWKNKQPEADI9CX9HCEVINXITKIOJVPBTGRJWDZI9LYDPXVLGTMBHNFIROHQ"
237-
"RRVNBBZVMNCCVGZW9OXHKQNLLPMTQGFEGLSYIOFJGXZ9SPYWIVZEZYIRAMROSWYZUIIUJVVPXVAONMOCYJJBKMQUO9"
238-
"OBBJXFNESYQXNWULUDSAWNBZOOGWQSUXZFMNRWCZGHT9KCIJPWYWXBNDYXGLGDDELQHYBFGVTTCJEIVYEJDCKRAECH"
239-
"CHPCGVSRJZJSDEATRIFOQXF9YMVQFSARZFQUGUSVKMUP9GNBTPRROTSZIEWXHPCBQYAUOXKFOZWDBKUFCKXNXMFZGV"
240-
"UEKCCLRWFBAKROVAVPNNRFYPEWBNXTWVGLZMOWAIEF9WOCGXZCVQXWFLUYAKFBRLABYUHNMBCAAFVADSPPOCKQXHTA"
241-
"KQLSOWPLFRVCNUQNNRLGKRFUARWJXGEABPIJWQX9TFQNPOSZZQPYDTNXDIBXVWQPYQDGPLXHXKQKGI9EAFQUFXMONE"
242-
"JXRFZMHJSDYBXHSBVBZCOZVNFQQKEISCOSYLWH9WTRSJYRBQJGUQQVBAUBNWYBIPZZQHMIUPHBTKIVXQ9DONMSWLRT"
243-
"EGWSUNSZWXWGUXG9YFXUHOKOJRMWNRXOYINKEJFZDOFENGSCFBJYNKBTZLDXYTPYYXYBWGZLATTFQYEDZRQMRROBGX"
244-
"HGGZXSCFR9SEDBQRMKXQXJETMJJMWGTUBBKARMZAUSENUCTRYOBTKISTSEPRPDXEPQ99HGAKOCXJN9PGKJVMMGITIU"
245-
"IIMFIQSYGIJ9I9JPVSPICRHPCXVRIZNTVQQSVTJZXEIHYXMOXDEFKDQBOEERRAWBRLNWUHJANYBXLIMOC9FNKUBXFC"
246-
"QXXPKOSMGPLZJHAYQV9LFNLVKSPGLIBPYACKKWHYIOFBUUJVEQQUJJFRSXWCTEVUNLKLMYGMSOCXCDAKSIOFKDWHQK"
247-
"OOCCHHYNTZLE99BQZ9VLCSML9RB",
248-
0, 1, "999999999999999999999999999999999999999999999999999999NFRPTDAX9XUSPAQBPVPFXF99EA9",
249-
"BIGFB9ABABLWWIRSYRDVFRVURZJLDCMOUGYYGNSKQ9JSLXGHXKZPCBMCEMFUIP9UMGRBIVVDQIHDZ9999",
250-
1507233573,
251-
"HYZJPVGLNYMHKMC9TRQXNXSSHZZUOUBZRJMLZETENPQKTIECOSG9CFLNVWNMSPXQGCHMTZT9OCR9A9999",
252-
"KTRETJZQNAZKOLFKJGQUYLSYVHTFJBE9MZCUOAWZXTFOHWMMZBPOFVGQCRSASCBKDQZRIXNILUZQ99999",
253-
"KPWCHICGJZXKE9GSUDXZYUAPLHAKAHYHDXNPHENTERYMMBQOPSQIDENXKLKCEYCPVTZQLEEJVYJZV9BWU", 0, "",
254-
"MNPL99999999999999999999999", 0, 0, 0 });
255-
256-
b.addTransaction(
257-
{ "BUZYVXO9XB99HAXGWEVDAAYDIUVINLZVQWGMGYMANUCVXFPQV9OAOBEPXBRYIKMUSGTCFZUSXTNNOELBBMRJ"
258-
"QXGLCYGUWBZVNOGPCLFJLMKIWXTTQBICGWJVHPLJWYJXUFUWRWMRWWZHCTXNYJFYTQNAWPSRYPI9LOPZRVFM"
259-
"ADJFQQ9BZUBKLMJLZSBSBFPWLUKJYZHTPCTJNALXTGSHHUZKNNIYREZOESRNFO9GFNPPNVUZ9KABTIYIALFI"
260-
"OLJYSUPQPFELKLZKBRZQXFEXIEGKZUMOAYCUQQOXELMOQJIFPCKDKVBJ9IZSTMBIPF9OMGXINNUFPVRNXLDC"
261-
"OQZOARW9DJFANYZXSZXMAWCOPHOY9XYCLNJRZRUHKHLPLHKWFPZWPSIWIWKZXZVSMGEIBSAULAGCSSVJZHNB"
262-
"THUCXIXXJPLFFE9ZEJPCLMIYKQCHTVRZPZELVGJAWMAHVDMUFKJHXLEWZWXQRYEPENVKPGMYNIGVQYJVQBYC"
263-
"PNDRSHYJV9HHKVCGKF99OZEBNLMQSPEJKPYDTYBUANSUMQDSCNGKKZKVSQFTO9LFKEUPWGAGYOJKTHPOAHJM"
264-
"RASHGDELFYSG9XDF9OYGMDYTCUMMOLUYMPC9FDPPKHLYZTMMFHZDPCWYBGMKVEOUXXOPN9RTQPOVETCHZHWG"
265-
"QZMADCXEVGTWXY9LBZBPYUMPQHOGWHRWK9XDOMDJAAZRSOOIYSWUVBXTVJWJBVNVPFEWEJZUJCKBEHBOGKZH"
266-
"ZE9COE9BDVGAMCJQDQZAFRWOFYXVUSIAJQSOC9SI9SEQGCKPGCXFXYSJNHTMHTXCRVYNPVSDYEUTHFYUAIKA"
267-
"PTMQLPXIGZHWO9BFZNOZC9VBJAVTJCUESQJDMBETBIZODVHZDSWQDOUIPCYTZCGOPMJJIDOTYPAMTTEXLVZ9"
268-
"CTARGVHAIQODWUHKEX9IDDD9HNBNYRVGI9LARZKMSTAJIHZWPPIAGTLFTPRAIJUFYYXTIJJZW9UEFJKQCKXW"
269-
"STKP9CSMXHCRCECZDBRHIABBIQEBYWNPFHXFFAYEOLDAHFOCVK9AAKF9EQLNFSDEORKFYXKUXSGSTQMBVRNI"
270-
"BOGUWYNJISWGTZRUBAUPSACRTWPAQIDXOXUXMKEVCDZLBUXWINABWYBDMZNIYNVPYLRKUULTMNNKZUFNQOQK"
271-
"ROJSXWYTBRDSJQKTOUXLMXVCVIXEYPZWBSMEXMBGUIVACRTGKDEIYZKP9KQCQXPWRXNLGQOATRHCXJFQINXF"
272-
"YQIDTPUJVXKUYVRYHWDHWSNLWUFPNNJZVNMRFWPZBJCRRSHMHUG9NKKH9SOXTUJUAXBF9MHYWHJ9ZTJRUQFK"
273-
"RLHMNVPWX9XFXLMVJAGASMWMIFYUZFAUCEIOOYMEYWOIZTNEWFVZKOQFECWEPSMOYFSJJKEJQMPSXGE9WTYR"
274-
"QJVMHUQZFD9MJUFFCNSGAZCTXYPIJFNSXAUCYPGZMNWMQWSWCKAQYKXJTWINSGPPZG9HLDLEAWUWEVCTVRCB"
275-
"DFOXKUROXH9HXXAXVPEJFRSLOGRVGYZASTEBAQNXJJROCYRTDPYFUIQJVDHAKEG9YACV9HCPJUEUKOYFNWDX"
276-
"CCJBIFQKYOXGRDHVTHEQUMHO999999999999999999999999999999999999999999999999999999999999"
277-
"999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
278-
"999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
279-
"999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
280-
"999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
281-
"999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
282-
"999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
283-
"999",
284-
1, 1, "999999999999999999999999999999999999999999999999999999OVATEWFUX9ORCXAETEZCEJZVOXG",
285-
"HYZJPVGLNYMHKMC9TRQXNXSSHZZUOUBZRJMLZETENPQKTIECOSG9CFLNVWNMSPXQGCHMTZT9OCR9A9999",
286-
1507233573,
287-
"KTRETJZQNAZKOLFKJGQUYLSYVHTFJBE9MZCUOAWZXTFOHWMMZBPOFVGQCRSASCBKDQZRIXNILUZQ99999",
288-
"UXWJUGEJFXZGOKZUOLVIUWBKYXWAQBDUMZYLTJUBRFXUWAY9DZHVHXCOYAJKLFOBXYOPLIBHIHQV99999",
289-
"999999999999999999999999999999999999999999999999999999999999999999999999999999999", 0, "",
290-
"999999999999999999999999999", 0, 0, 0 });
222+
b.addTransaction(IOTA::Models::Transaction(BUNDLE_1_TRX_1_TRYTES));
223+
b.addTransaction(IOTA::Models::Transaction(BUNDLE_1_TRX_2_TRYTES));
224+
b.addTransaction(IOTA::Models::Transaction(BUNDLE_1_TRX_3_TRYTES));
225+
b.addTransaction(IOTA::Models::Transaction(BUNDLE_1_TRX_4_TRYTES));
291226

292227
b.finalize();
293228

294229
for (const auto& trx : b.getTransactions()) {
295-
EXPECT_EQ(trx.getBundle(),
296-
"OE9RXPMWDVHVQSDAQSUQBXAIBTFTEJWOFFD99CLBACFTVGLRNIMKSEMSAF9XZLGYMFAEAQXKUNCORMUAD");
230+
EXPECT_EQ(trx.getBundle(), BUNDLE_1_HASH);
297231
}
298232
}
299233

0 commit comments

Comments
 (0)