| 1346 | } |
| 1347 | |
| 1348 | void BlockChainState::spend_output( |
| 1349 | OutputIndexData &&output, size_t hidden_index, size_t trigger_input_index, size_t level, bool spent) { |
| 1350 | if (level >= 5) |
| 1351 | m_log(logging::INFO) << "Sure spent level=" << level << " hi=" << hidden_index; |
| 1352 | auto key = OUTPUT_PREFIX + common::write_varint_sqlite4(hidden_index); |
| 1353 | bool no_subgroup_check_aftermath = hidden_index == 35654297 || hidden_index == 35655016; |
| 1354 | if (spent) { |
| 1355 | invariant(no_subgroup_check_aftermath || output.spent == 0, ""); |
| 1356 | output.spent += 1; |
| 1357 | } else { |
| 1358 | invariant(no_subgroup_check_aftermath || output.spent == 1, ""); |
| 1359 | output.spent -= 1; |
| 1360 | } |
| 1361 | m_db.put(key, seria::to_binary(output), false); |
| 1362 | if (spent && output.spent > 1) |
| 1363 | return; |
| 1364 | if (!spent && output.spent > 0) |
| 1365 | return; |
| 1366 | if (!spent) // Not the fastest code, but undo is rare |
| 1367 | std::reverse(output.dins.begin(), output.dins.end()); |
| 1368 | for (auto input_index : output.dins) { |
| 1369 | if (input_index == trigger_input_index) |
| 1370 | continue; |
| 1371 | auto din_key = DIN_PREFIX + common::write_varint_sqlite4(input_index); |
| 1372 | BinaryArray din_ba; |
| 1373 | invariant(m_db.get(din_key, din_ba), ""); |
| 1374 | InputDesc din; |
| 1375 | seria::from_binary(din, din_ba); |
| 1376 | size_t only_index = std::numeric_limits<size_t>::max(); |
| 1377 | if (spent) { |
| 1378 | size_t found_index = std::lower_bound(din.first.begin(), din.first.end(), hidden_index) - din.first.begin(); |
| 1379 | invariant(found_index != din.first.size() && din.first.at(found_index) == hidden_index, ""); |
| 1380 | din.first.erase(din.first.begin() + found_index); |
| 1381 | din.second.push_back(hidden_index); |
| 1382 | // std::cout << "Removing hidden_index " << hidden_index << " from " << din.tid << ":" << |
| 1383 | // din.index << std::endl; |
| 1384 | if (din.first.size() == 1) { |
| 1385 | only_index = din.first.back(); |
| 1386 | } |
| 1387 | } else { |
| 1388 | if (din.first.size() == 1) { |
| 1389 | only_index = din.first.back(); |
| 1390 | } |
| 1391 | invariant(!din.second.empty() && din.second.back() == hidden_index, ""); |
| 1392 | din.second.pop_back(); |
| 1393 | size_t insert_index = |
| 1394 | std::lower_bound(din.first.begin(), din.first.end(), hidden_index) - din.first.begin(); |
| 1395 | din.first.insert(din.first.begin() + insert_index, hidden_index); |
| 1396 | } |
| 1397 | m_db.put(din_key, seria::to_binary(din), false); |
| 1398 | if (only_index != std::numeric_limits<size_t>::max()) { |
| 1399 | OutputIndexData unp; |
| 1400 | invariant(read_hidden_amount_output(only_index, &unp), ""); |
| 1401 | spend_output(std::move(unp), only_index, input_index, level + 1, spent); |
| 1402 | } |
| 1403 | } |
| 1404 | } |
| 1405 | |