|
COOPENOMICS
v1
Кооперативная Экономика
|
Пространства имен | |
| namespace | anonymous_namespace{migrate.cpp} |
| Миграция остатков с legacy-ledger на ledger2 (пересмотр 2026-04-20). | |
Функции | |
| void | ledger2::apply (eosio::name coopname, eosio::name initiator, eosio::name operation_code, eosio::asset amount, eosio::name username, eosio::checksum256 process_hash, std::string memo) |
| Единая точка входа финансовых движений ledger2 (orchestrator). Подробнее... | |
| void | ledger2::walletop (eosio::name coopname, uint8_t op_code, eosio::name wallet_from, eosio::name wallet_to, eosio::asset amount, eosio::checksum256 process_hash, std::string memo) |
| Атомарная операция по кошельку (issue/transfer/block/unblock). Подробнее... | |
| void | ledger2::debit (eosio::name coopname, uint64_t account_id, eosio::asset amount, eosio::checksum256 process_hash, std::string memo) |
| Атомарная дебетовая проводка на счёт + пересчёт сальдо. Подробнее... | |
| void | ledger2::credit (eosio::name coopname, uint64_t account_id, eosio::asset amount, eosio::checksum256 process_hash, std::string memo) |
| Атомарная кредитовая проводка на счёт + пересчёт сальдо. Подробнее... | |
| void | ledger2::migrate (uint64_t from_coop_index, uint64_t limit) |
| Миграция остатков с legacy-ledger в ledger2 (курсорный режим). Подробнее... | |
| void | ledger2::walmove (eosio::name coopname, eosio::name initiator, eosio::name username, eosio::name from_wallet, eosio::name to_wallet, eosio::asset amount, eosio::checksum256 process_hash, std::string memo) |
| Перевод между кошельками внутри одного бух.счёта (operation o.adj.walmove). Подробнее... | |
| void | ledger2::revert (eosio::name coopname, eosio::name initiator, uint64_t original_operation_id, eosio::name original_operation_code, eosio::name username, eosio::asset amount, uint8_t mirror_wallet_op, eosio::name mirror_wallet_from, eosio::name mirror_wallet_to, uint64_t mirror_debit_account_id, uint64_t mirror_credit_account_id, eosio::checksum256 process_hash, std::string memo) |
| Откат ранее проведённой операции (operation o.adj.rev). Подробнее... | |
| void ledger2::apply | ( | eosio::name | coopname, |
| eosio::name | initiator, | ||
| eosio::name | operation_code, | ||
| eosio::asset | amount, | ||
| eosio::name | username, | ||
| eosio::checksum256 | process_hash, | ||
| std::string | memo | ||
| ) |
Единая точка входа финансовых движений ledger2 (orchestrator).
Единая точка входа ledger2 для финансовых движений (orchestrator).
Не пишет в state напрямую: рассылает 3 atomic inline action (walletop, debit, credit), связанных общим process_hash.
Пересмотр 2026-04-18 (Epic 1 addendum): apply ничего не пишет в state напрямую. Это orchestrator, который рассылает 3 атомарных inline action:
Все три inline-actions передают единый process_hash, что позволяет бэкенду собрать «тройку» из blockchain_actions: WHERE account = 'ledger2' AND data->>'process_hash' = X
История проводок не хранится в RAM-таблицах — она целиком восстанавливается на бэкенде из blockchain_actions (для apply/walletop/debit/credit) и blockchain_deltas (для accounts2 и wallets2). Это даёт:
| void ledger2::credit | ( | eosio::name | coopname, |
| uint64_t | account_id, | ||
| eosio::asset | amount, | ||
| eosio::checksum256 | process_hash, | ||
| std::string | memo | ||
| ) |
Атомарная кредитовая проводка на счёт + пересчёт сальдо.
Атомарная кредитовая проводка на счёт ledger2.
Внутренний action — вызывается только через inline из apply().
Внутренний action ledger2 — вызывается только через inline из apply(). Auth: только сам ledger2 (require_auth(get_self())).
Прибавляет amount к accounts2[account_id].credit_balance, затем пересчитывает balance согласно account_type. Парная debit-проводка приходит отдельным inline (action debit) с тем же process_hash — бэкенд связывает их в пару.
TODO(payer, 2026-04-18): payer = get_self() → RAM ledger2. Перевести на coopname при общем переходе на coopname-eosio.code permissions. См. Decision #D2 в code review Epic 1.
| void ledger2::debit | ( | eosio::name | coopname, |
| uint64_t | account_id, | ||
| eosio::asset | amount, | ||
| eosio::checksum256 | process_hash, | ||
| std::string | memo | ||
| ) |
Атомарная дебетовая проводка на счёт + пересчёт сальдо.
Атомарная дебетовая проводка на счёт ledger2.
Внутренний action — вызывается только через inline из apply().
Внутренний action ledger2 — вызывается только через inline из apply(). Auth: только сам ledger2 (require_auth(get_self())).
Прибавляет amount к accounts2[account_id].debit_balance, затем пересчитывает balance согласно account_type. Парная credit-проводка приходит отдельным inline (action credit) с тем же process_hash — бэкенд связывает их в пару.
TODO(payer, 2026-04-18): payer = get_self() → RAM ledger2. Перевести на coopname при общем переходе на coopname-eosio.code permissions. См. Decision #D2 в code review Epic 1.
| void ledger2::migrate | ( | uint64_t | from_coop_index, |
| uint64_t | limit | ||
| ) |
Миграция остатков с legacy-ledger в ledger2 (курсорный режим).
| from_coop_index | начальный индекс в таблице registrator::coops (0 — с начала) |
| limit | максимум кооп. за один вызов (UINT64_MAX — до конца) |
Полный прогон: migrate(0, UINT64_MAX). Продовый прогон порциями: migrate(0, 10), migrate(10, 10), ... Мета-таблица хранит last_migrated_coop_index для возобновления.
Все балансы вносятся через inline apply(operations::migration::*) — единый путь учёта с полной двойной проводкой и audit-trail (пересмотр 2026-04-20: детерминированное разнесение на 6 целевых кошельков без транзитного счёта 99 и без зеркала CASH_MAIN).
| void ledger2::revert | ( | eosio::name | coopname, |
| eosio::name | initiator, | ||
| uint64_t | original_operation_id, | ||
| eosio::name | original_operation_code, | ||
| eosio::name | username, | ||
| eosio::asset | amount, | ||
| uint8_t | mirror_wallet_op, | ||
| eosio::name | mirror_wallet_from, | ||
| eosio::name | mirror_wallet_to, | ||
| uint64_t | mirror_debit_account_id, | ||
| uint64_t | mirror_credit_account_id, | ||
| eosio::checksum256 | process_hash, | ||
| std::string | memo | ||
| ) |
Откат ранее проведённой операции (operation o.adj.rev).
Создаёт зеркальную проводку по операции original_operation_id: меняет местами Dr/Cr счета и (для wallet_op) wallet_from/wallet_to. Для исходного ISSUE используется новый WalletOp::REVOKE (изъятие с wallet_from без увеличения куда-либо).
Параметры зеркала готовит backend из своей БД (по записи оригинала в blockchain_actions/state) — контракт не имеет доступа к истории операций.
Запрещено откатывать миграционные операции (operation_code starts with o.mig.). Повторный откат отката (revert от revert) разрешён.
Auth: coopname@active (председатель).
| coopname | кооператив (payer auth) |
| initiator | инициатор отката (для аудита) |
| original_operation_id | id оригинальной записи в blockchain_actions |
| original_operation_code | operation_code оригинала (для запрета o.mig.*) |
| username | username оригинала (для аналитики) |
| amount | сумма (как в оригинале) |
| mirror_wallet_op | тип wallet-операции зеркала (REVOKE/TRANSFER/WALLET_ONLY) |
| mirror_wallet_from | кошелёк-источник зеркала |
| mirror_wallet_to | кошелёк-получатель зеркала (пустое имя для REVOKE) |
| mirror_debit_account_id | Dr-счёт зеркала (0 для WALLET_ONLY) |
| mirror_credit_account_id | Cr-счёт зеркала (0 для WALLET_ONLY) |
| process_hash | уникальный хэш для зеркальной операции |
| memo | обязательное обоснование (≤ 255 символов) |
Contract-only: top-level вызов председателем (coopname@active) запрещён. Action принимает только подпись от whitelisted контрактов (contracts_whitelist) — то есть зеркальная проводка возможна только когда её инициирует другой контракт-инициатор (registrator/wallet/capital/...), который параллельно откатывает свой собственный state.
Why this restriction: ledger2 — учётный слой; зеркальная проводка не трогает сущности контрактов-инициаторов (participants/deposits/contributors). Top-level откат председателем рассинхронизирует учёт и состояние домена (например, participant остаётся accepted, а минимальный паевой «вернулся»).
Контракт не имеет доступа к истории blockchain_actions — параметры зеркала собирает контракт-инициатор (он знает свой исходный operation_code и соответствующие Dr/Cr/wallet через operations.hpp registry).
Запрет на откат миграционных операций (o.mig.*) сохранён. Повторный откат отката (revert от revert) разрешён.
| void ledger2::walletop | ( | eosio::name | coopname, |
| uint8_t | op_code, | ||
| eosio::name | wallet_from, | ||
| eosio::name | wallet_to, | ||
| eosio::asset | amount, | ||
| eosio::checksum256 | process_hash, | ||
| std::string | memo | ||
| ) |
Атомарная операция по кошельку (issue/transfer/block/unblock).
Внутренний action — вызывается только через inline из apply().
Внутренний action ledger2 — вызывается только через inline из apply(). Auth: только сам ledger2 (require_auth(get_self())).
Ровно одна мутация wallets2: ISSUE добавляет на wallet_to, TRANSFER перемещает wallet_from → wallet_to, BLOCK/UNBLOCK переносит между available и blocked на wallet_from.
История этого вызова автоматически попадает в blockchain_actions с полями (op_code, wallet_from, wallet_to, amount, process_hash, memo) — этого достаточно бэкенду для восстановления wjournal-эквивалента.
TODO(payer, 2026-04-18): сейчас payer = get_self() (ledger2), что даёт неограниченный рост RAM контракта. Перевести на payer = coopname, когда все caller-контракты возьмут у coopname разрешение eosio.code → ledger2 через linkauth. Решение по code review Decision #D2.
| void ledger2::walmove | ( | eosio::name | coopname, |
| eosio::name | initiator, | ||
| eosio::name | username, | ||
| eosio::name | from_wallet, | ||
| eosio::name | to_wallet, | ||
| eosio::asset | amount, | ||
| eosio::checksum256 | process_hash, | ||
| std::string | memo | ||
| ) |
Перевод между кошельками внутри одного бух.счёта (operation o.adj.walmove).
Ручная корректировка председателя: переносит amount с from_wallet на to_wallet БЕЗ движения по бух.счетам (debit/credit не вызываются). Применение: разнесение по аналитическим кошелькам после криво легшей миграции (типичный кейс voskhod), мелкие исправления в рамках одного фонда.
Auth: coopname@active (председатель). Audit: action+inline walletop попадают в blockchain_actions с общим process_hash, бэкенд видит как один процесс processes::adjustment::CORRECTION (p.adj.fix).
Валидация: from_wallet ≠ to_wallet, оба в LEDGER2_WALLET_REGISTRY, memo не пуст. Соответствие account_id для двух кошельков обеспечивает UI/backend (контракт не хранит wallet→account mapping).
| coopname | кооператив (одновременно payer auth) |
| initiator | инициатор корректировки (для аудита; обычно совпадает с coopname) |
| username | владелец кошельков (для аналитики; обычно coopname для коллективных кошельков) |
| from_wallet | кошелёк-источник |
| to_wallet | кошелёк-получатель |
| amount | сумма в _root_govern_symbol |
| process_hash | уникальный хэш корректировки (генерирует backend) |
| memo | обязательное обоснование (≤ 255 символов) |
Top-level action — председатель подписывает сам, никаких caller-контрактов. Делает один inline walletop с op_code = WALLET_ONLY (TRANSFER без Dr/Cr) — так как корректировка между кошельками одного бух.счёта не меняет балансы самих счетов (accounts2.balance), только их аналитику.
Связь wallet→account не хранится в LEDGER2_WALLET_REGISTRY (она выводится из OPERATION_REGISTRY по месту использования и может теоретически быть многозначной), поэтому соответствие двух кошельков одному account_id проверяется на стороне backend (резолвер walmoveWallets смотрит Ledger2.LEDGER2_OPERATION_REGISTRY и отказывает на разные account_id).