COOPENOMICS  v1
Кооперативная Экономика
Пространство имен anonymous_namespace{migrate.cpp}

Миграция остатков с legacy-ledger на ledger2 (пересмотр 2026-04-20). Подробнее...

Классы

struct  LegacyBalances
 

Функции

LegacyBalances read_legacy_balances (eosio::name coopname)
 
eosio::asset sum_progwallet_blocked (eosio::name coopname, uint64_t program_id)
 
eosio::asset compute_min_total_by_type (eosio::name coopname, const cooperative2 &coop)
 
void send_transit (eosio::name self_name, eosio::name coopname, eosio::name operation_code, const eosio::asset &amt)
 
void emplace_wallet_only (eosio::name self_name, eosio::name coopname, eosio::name wallet_id, const eosio::asset &amt)
 
void migrate_voskhod_facts (eosio::name self_name, const cooperative2 &coop)
 
void migrate_one_coop (eosio::name self_name, const cooperative2 &coop)
 

Подробное описание

Миграция остатков с legacy-ledger на ledger2 (пересмотр 2026-04-20).

Разделение на два независимых потока:

A. Бухгалтерские остатки из ledger::accounts (scope=coopname, contract=_ledger) → через 4 inline apply(operations::migration::*) с полной двойной проводкой. Счета: 51 / 80 / 86 / 04.

B. Программные кошельки из soviet::progwallets (scope=coopname, contract=_soviet) → прямой wallets2.emplace в ledger2 БЕЗ бух-проводок. Legacy::accounts и soviet::progwallets — параллельные системы учёта, progwallet.blocked не проводится через 80-й счёт, поэтому любая попытка провести его через Dr 51 / Cr 80 вызовет двойной учёт на бухуровне. Вместо этого переносим только wallet-аналитику (w.cap.bginv BLAGOROST_INVEST, w.cap.gncom GENERATOR_COMMIT).

Алгоритм на каждый кооператив:

  1. Чтение legacy-счетов (laccounts_index, scope=coopname): cash_legacy = account[51].available + .blocked share_legacy = account[80].available + .blocked entry_legacy = account[861].available + .blocked
  2. Чтение параметров кооператива (cooperative2, scope=_registrator): coop.minimum — минимальный паевой для individual / entrepreneur coop.org_minimum — минимальный паевой для organization (binary_extension)
  3. Вычисление распределения: share_money = cash_legacy − entry_legacy rid_share = share_legacy − share_money min_total = clamp(Σ accepted-пайщиков по типу, 0, share_money) где для organization берётся coop.org_minimum, иначе — coop.minimum (см. compute_min_total_by_type). share_remain = share_money − min_total

    Инварианты (eosio::check): cash_legacy >= entry_legacy share_legacy >= share_money

  4. Отправка 4 inline apply (ненулевые пропускаются): apply(migration::MIN_SHARE, min_total) → Dr 51 / Cr 80, MIN_SHARE_FUND (w.reg.minshr) apply(migration::SHARE, share_remain) → Dr 51 / Cr 80, SHARE_FUND_PAY (w.wal.share) apply(migration::ENTRY, entry_legacy) → Dr 51 / Cr 86, ENTRANCE_FEES (w.reg.entry) apply(migration::RID, rid_share) → Dr 04 / Cr 80, SHARE_FUND_RID (w.wal.sharid)
  5. Прямой emplace в wallets2 для progwallets (БЕЗ бух-проводок): Σ progwallet[blagorost].blocked → wallets2[BLAGOROST_INVEST w.cap.bginv] Σ progwallet[generator].blocked → wallets2[GENERATOR_COMMIT w.cap.gncom]

    Если запись wallets2 уже есть (после inline apply сработали) — aggregate через wallets.modify(available += sum). Иначе — emplace.

Курсорный режим: migrate(from_coop_index, limit). Полный прогон — migrate(0, UINT64_MAX). Мета фиксирует last_migrated_coop_index.

Поле writeoff legacy-ledger игнорируется целиком (PRD §4.1.2 FR-L-7).

Функции

◆ compute_min_total_by_type()

eosio::asset anonymous_namespace{migrate.cpp}::compute_min_total_by_type ( eosio::name  coopname,
const cooperative2 coop 
)
inline

Считает суммарный «минимальный паевой» по всем accepted-пайщикам коопа с учётом типа: organization → coop.org_minimum, иначе → coop.minimum.

Кэш cooperative2.active_participants_count не используется — он не несёт разбивку по типу. Идём по participants_index напрямую.

Если у пайщика поле type не заполнено (legacy-записи), считаем как individual (берём coop.minimum). Если у коопа отсутствует org_minimum (binary_extension не выставлен) — fallback тоже на coop.minimum, чтобы не уронить миграцию на старых конфигах.

◆ emplace_wallet_only()

void anonymous_namespace{migrate.cpp}::emplace_wallet_only ( eosio::name  self_name,
eosio::name  coopname,
eosio::name  wallet_id,
const eosio::asset &  amt 
)
inline

Прямой emplace/add в wallets2 БЕЗ бух-проводок. Используется для переноса соwiet::progwallets → wallets2, т.к. progwallets не проводятся через ledger::accounts (параллельная система учёта — двойная запись не нужна и привела бы к двойному учёту на 80).

◆ migrate_one_coop()

void anonymous_namespace{migrate.cpp}::migrate_one_coop ( eosio::name  self_name,
const cooperative2 coop 
)
inline

Мигрирует один кооператив. Отправляет до 4 inline apply (бух-проводки)

  • прямой emplace программных кошельков (без проводок).

Для voskhod — спец-ветка по фактам (см. migrate_voskhod_facts), т.к. legacy::accounts и soviet::progwallets рассинхронизированы.

◆ migrate_voskhod_facts()

void anonymous_namespace{migrate.cpp}::migrate_voskhod_facts ( eosio::name  self_name,
const cooperative2 coop 
)
inline

Спец-ветка миграции для voskhod — РУЧНОЙ ХАРДКОД сумм по кошелькам.

Цифры заведены вручную после сверки с фактическими данными mainnet (snapshot 2026-04-29). При необходимости править — править прямо здесь, пересобирать ledger2.wasm и катить.

Причина хардкода: legacy::accounts и soviet::progwallets рассинхронизированы (деньги Благороста, прошедшие через 51, разошлись 80 vs progwallets, есть бумажный шлейф на 51, и т.п.). Вместо арифметической сшивки — заводим суммы вручную по тому, как кооператив должен выглядеть в ledger2.

Имущественная часть на legacy 80 (РИД ~56.8M) сюда НЕ заводится отдельным w.wal.sharid: она остаётся осадком на legacy 80 до Phase 2 (ADR-009), когда Благорост схлопнется в w.cap.blago и заберёт имущество.

Бух-баланс по этой таблице: Dr 51 = w.reg.minshr + w.wal.share + w.reg.entry = 31800 + 569900 + 12500 = 614200 Cr 80 = w.reg.minshr + w.wal.share = 31800 + 569900 = 601700 Cr 86 = w.reg.entry = 12500 Σ Dr = Σ Cr = 614200 ✓

Σ Благороста на bginv (57 044 311) и Генератора на gncom (0) идут прямым emplace без бух-проводок (параллельный progwallets-учёт).

◆ read_legacy_balances()

LegacyBalances anonymous_namespace{migrate.cpp}::read_legacy_balances ( eosio::name  coopname)
inline

◆ send_transit()

void anonymous_namespace{migrate.cpp}::send_transit ( eosio::name  self_name,
eosio::name  coopname,
eosio::name  operation_code,
const eosio::asset &  amt 
)
inline

Отправляет inline apply для одной миграционной операции, если amount > 0. process_hash детерминирован по (coopname, operation_code).

◆ sum_progwallet_blocked()

eosio::asset anonymous_namespace{migrate.cpp}::sum_progwallet_blocked ( eosio::name  coopname,
uint64_t  program_id 
)
inline

Суммирует blocked по progwallets (soviet, scope=coopname) для program_id.