তথ্যসূত্র / প্রমাণ
স্বতন্ত্র সাক্ষী
নিজের কী এবং বট সহ একটি উইটনেস চালান, চ্যানেলে স্বাক্ষরিত চেকপয়েন্ট প্রকাশ করুন এবং এর বিপরীতে এক্সপোর্টগুলো যাচাই করুন।
বট এবং প্রক্সি সেটিংস রুশ ভাষায়।
একজন কালেক্টর তার নিজস্ব জার্নালে স্বাক্ষর করে, তাই যে কেউ কালেক্টর এবং এর কী নিয়ন্ত্রণ করে, তাত্ত্বিকভাবে জার্নালটি পুনঃলিখন বা সংক্ষিপ্ত করে আবার স্বাক্ষর করতে পারে। একজন সাক্ষী এটিকে শনাক্তযোগ্য করে তোলে। এটি একটি পৃথক প্রক্রিয়া — আরেকটি কন্টেইনার, বা আরও ভালোভাবে বলতে গেলে অন্য কেউ চালানো একটি সার্ভার — যা প্রতি কয়েক মিনিটে কালেক্টরের স্বাক্ষরিত জার্নাল হেড সংগ্রহ করে, যা দেখে তা নিজের কী দিয়ে স্বাক্ষর করে, নিজের জার্নালে সংরক্ষণ করে এবং একটি টেলিগ্রাম চ্যানেলে পোস্ট করে।
ডায়াগ্রাম টেক্সট হিসেবে
- সংগ্রাহক → সাক্ষী (স্বাক্ষরিত চেকপয়েন্ট: রেকর্ড গণনা + হেড হ্যাশ)
- সাক্ষী → সাক্ষী জার্নাল, নিজস্ব কী
- সাক্ষী → টেলিগ্রাম চ্যানেল (নিজের বটের মাধ্যমে স্বাক্ষরিত পোস্ট)
- প্রমাণ ZIP → verify.py
- সাক্ষী জার্নাল, নিজস্ব কী → verify.py
- টেলিগ্রাম চ্যানেল → verify.py (টেলিগ্রাম ডেস্কটপ এক্সপোর্ট অথবা t.me/s পৃষ্ঠা)
সাক্ষী যা পায় এবং যা পায় না#
| সাক্ষীর আছে | সাক্ষী কখনোই করেনি। |
|---|---|
| একটি ওয়ার্কস্পেসের জন্য শুধুমাত্র-পঠনযোগ্য সাক্ষী টোকেন | সংগ্রাহকের টেলিগ্রাম সেশন বা API ক্রেডেনশিয়ালস |
| এর নিজস্ব Ed25519 কী এবং জার্নাল | সংগ্রাহকের ভল্ট, স্বাক্ষর কী বা প্যানেল টোকেন |
| এর নিজস্ব টেলিগ্রাম বট টোকেন | বার্তার বিষয়বস্তু: হেড হল একটি রেকর্ড গণনা এবং একটি হ্যাশ |
টোকেনটি প্যানেলের উইটনেস পেজে তৈরি হয়, একবার প্রদর্শিত হয় এবং শুধুমাত্র SHA-256 হিসেবে সংরক্ষিত থাকে। এটি ঠিক একটি এন্ডপয়েন্ট, GET /api/witness/head, খুলে, যা একটি সদ্য স্বাক্ষরিত চেকপয়েন্ট এবং স্বাক্ষরিত বিষয়বস্তুবিহীন সংগ্রহ কাউন্টার ও অপারেশনাল হেলথ ফেরত দেয়।
এটি প্যানেল খুলতে, বার্তার বিষয়বস্তু পড়তে বা সেটিংস পরিবর্তন করতে পারে না, এবং প্যানেল টোকেন সেখানে গ্রহণযোগ্য নয়। একই পৃষ্ঠায় টোকেন বাতিল করুন। কালেক্টর রেকর্ড করে কখন একটি নতুন উইটনেস কী (witness.seen) যাচাই শুরু করে এবং প্রতিটি টোকেনের শেষ যাচাই দেখায়; যে উইটনেস ২.৫ ইন্টারভালের মধ্যে যাচাই হয়নি, তাকে সময়সীমা অতিক্রান্ত (overdue) হিসেবে চিহ্নিত করা হয়।
নতুন সাক্ষীরা প্রতিটি পোল-এ একটি এলোমেলো চ্যালেঞ্জ পাঠায়; capture বিবৃতিটি এটিকে কালেক্টর স্বাক্ষরের নিচে প্রতিধ্বনিত করে। কাউন্টারগুলো নির্দিষ্ট চেকপয়েন্টের সাথে আবদ্ধ এবং স্বাক্ষরিত সাক্ষী পোস্টে অন্তর্ভুক্ত থাকে। লিগ্যাসি হেডগুলো স্বতন্ত্র সাক্ষীর দ্বারা গ্রহণযোগ্য থাকে। শুধুমাত্র জার্নাল বৃদ্ধি কখনোই নতুন বার্তা হিসেবে গণ্য হয় না।
এটি যা যাচাই করে এবং রেকর্ড করে#
প্রতিটি ব্যবধান (ডিফল্ট ১০ মিনিট) সাক্ষী:
- এটি হেডটিকে নিজেই আনয়ন করে (কলেক্টর এটিকে পুশ বা স্কিপ করতে পারে না);
- সংগ্রাহকের স্বাক্ষর যাচাই করে, পিন করা সংগ্রাহক কী (
--collector-fingerprintঅথবা প্রথম দেখা কী), একটি অ-হ্রাসমান গণনা এবং অপরিবর্তিত গণনায় অপরিবর্তিত হেড; - নিজের জার্নালে একটি স্বাক্ষরিত রেকর্ড সংযুক্ত করে:
witness.anchor, স্ট্যাটাসok,key_changed,rollback(আগের তুলনায় কম রেকর্ড),fork(একই দৈর্ঘ্য, ভিন্ন হেড) অথবাinvalid(উত্তর যাচাইকরণে ব্যর্থ), অথবাwitness.no_responseযখন কালেক্টর উত্তর দেয়নি; - চ্যানেলে ফলাফলটি স্বাক্ষরিত অবস্থায় পোস্ট করা হয়, যার মধ্যে "no answer" অন্তর্ভুক্ত, যখন সাক্ষী চলছে এবং Bot API-তে পৌঁছাতে পারে। পোস্ট আইডি (
witness.posted) এবং একটি ব্যর্থ পোস্ট (witness.post_failed) রেকর্ড করা হয়।
একটি পোস্ট এরকম দেখায়; শেষ লাইনে স্বাক্ষরিত বিবৃতি থাকে:
TgWitness witness #42 · journal head
Collector 3fa9c2d1e0b4a7f6: 18234 records
Head 9b1f…c07e
2026-10-28T19:40:00.123+00:00
TGW1.eyJhdCI6…<statement>.<signature>
একজন সাক্ষী চালাও#
আপনাকে একটি টেলিগ্রাম বট (@BotFather দিয়ে তৈরি করুন), একটি চ্যানেল যেখানে সেই বট প্রশাসক, এবং সাক্ষীর কাছ থেকে HTTPS-এর মাধ্যমে ব্যক্তিগত নেটওয়ার্কের বাইরে পৌঁছানো যায় এমন কালেক্টরের ঠিকানা প্রয়োজন (ডিপ্লয়মেন্টে HTTPS প্রোফাইল দেখুন)।
এক্সট্রা → আপনার চ্যানেলে একটি বট →
প্যানেলে একটি বট সেট আপ
করুন। তিনটি ধাপে রয়েছে শুধুমাত্র-পঠন অ্যাক্সেস, আপনার চ্যানেল এবং ইন্টারভাল, তারপর উইটনেস চালু করা। প্রকাশ নীতি, ঐচ্ছিক HTTP/SOCKS5 প্রক্সি এবং কাস্টম বট API ঠিকানা অ্যাডভান্সড
সেটিংসে রয়েছে। ফর্মটি এই ওয়ার্কস্পেসের কালেক্টর কী পিন করে witness.json
ডাউনলোড করে। নতুন তৈরি করা রিড-অনলি টোকেনটি 'Save access file
as' হিসেবে witness-token.txt
ডাউনলোড করুন; এটি এবং উইটনেস হোস্টে তৈরি করা একটি bot-token.txt
সেই JSON-এর পাশে রাখুন। কালেক্টর কখনোই বট টোকেন পায় না।
ডাউনলোড করা কোনো সার্ভিস শুরু করে না বা কোনো বার্তা প্রকাশ করে না। কোনো হোস্টেড প্রকল্প উইটনেস স্বয়ংক্রিয়ভাবে অন্তর্ভুক্ত হয় না।
python -m tgwitness.witness run --config witness.json --check-config
python -m tgwitness.witness run --config witness.json
python -m tgwitness.witness fingerprint --config witness.json
প্রথম কমান্ডটি কোনো নেটওয়ার্ক অনুরোধ বা কী তৈরি ছাড়াই কনফিগারেশন এবং গোপন ফাইলগুলো পরীক্ষা করে। JSON-এ পথগুলো সেই ফাইলের সাপেক্ষে; CLI/পরিবেশের পথগুলো কর্ম ডিরেক্টরির সাপেক্ষে। সাক্ষীর ফিঙ্গারপ্রিন্ট হোস্টের বাইরে সংরক্ষণ করুন। কালেক্টরের last-poll সূচক শুধুমাত্র অনুরোধ নিশ্চিত করে; প্রকাশ Proof দ্বারা রিপোর্ট করা হয় অথবা সাক্ষীর জার্নাল এবং চ্যানেলে যাচাই করা হয়।
যদি প্যানেলটি একটি SSH টানেলের পিছনে থাকে, তাহলে এই Caddy উদাহরণ ব্যবহার করে শুধুমাত্র স্কোপড উইটনেস এন্ডপয়েন্টটিকে একটি আলাদা HTTPS হোস্টনেমে প্রকাশ করুন। ডিফল্ট ওয়ার্কস্পেস তখন https://witness.example.org ব্যবহার করে, অন্য ওয়ার্কস্পেসগুলো
https://witness.example.org/profiles/ID ব্যবহার করে। টোকেন এখনও প্রয়োজন; প্যানেল এবং এর অন্যান্য API রুটগুলো সেই ভার্চুয়াল হোস্ট দ্বারা ফরওয়ার্ড করা হয় না।
all-কে বেছে নিন নিয়মিত প্রকাশিত চেকপয়েন্টের জন্য। পাঁচ মিনিটের ব্যবধান মানে প্রতিদিন প্রতিটি ওয়ার্কস্পেসে প্রায় ২৮৮টি পোস্ট। changes/problems ইচ্ছাকৃতভাবে কিছু চেক প্রকাশ করে না।
MTProxy হল কালেক্টরের টেলিগ্রাম ক্লায়েন্টের জন্য। উইটনেস HTTP পোলিং এবং টেলিগ্রামের HTTPS
Bot API তাদের নিজস্ব ডাইরেক্ট/HTTP/SOCKS5 রুট (Bot API) ব্যবহার করে।
কলেক্টরের পাশে, ডকার ব্যবহার করে (একই হোস্ট—স্বতন্ত্র প্রসেস এবং কী, তবে একই অপারেটর): .env-এ মানগুলো রাখুন এবং প্রোফাইল শুরু করুন।
TGWITNESS_WITNESS_TOKEN=tgww_...
TGWITNESS_WITNESS_BOT_TOKEN=123456:ABC...
TGWITNESS_WITNESS_CHANNEL=@your_witness_channel
# another workspace: TGWITNESS_WITNESS_COLLECTOR=http://tgwitness:8787/profiles/<workspace ID>
docker compose --profile witness up -d
docker compose logs witness # prints the witness key fingerprint
প্রকাশিত ছবির জন্য docker compose --project-directory . -f deploy/compose/compose.image.yaml --profile witness up -d ব্যবহার করুন।
অন্য কারো সার্ভারে (একজন প্রকৃত স্বাধীন সাক্ষী): সেখানে রিপোজিটরিটি কপি করুন,
TGWITNESS_WITNESS_COLLECTOR=https://your-collector.example.org-এ .env-এ উপরের তিনটি মান যোগ করুন, তারপর
docker compose --project-directory . -f deploy/compose/compose.witness.yaml up -d
অথবা ডকার ছাড়া:
python -m tgwitness.witness run --collector https://your-collector.example.org \
--token-file witness-token.txt --bot-token-file bot-token.txt --channel @your_witness_channel
বিকল্পসমূহ#
| বিকল্প | পরিবেশ | ডিফল্ট | অর্থ |
|---|---|---|---|
--interval |
TGWITNESS_WITNESS_INTERVAL |
10 | চেকের মধ্যবর্তী মিনিট, ১–১৪৪০ |
--timeout |
_TIMEOUT |
30 | কলেক্টর এবং বট এপিআইয়ের জন্য অপেক্ষার সেকেন্ড, ৫–৬০০ |
--post |
_POST |
all |
all: প্রতিটি পরীক্ষা; changes: একটি নতুন সমস্যা বা কোনো সমস্যা; problems: শুধুমাত্র সমস্যা এবং অনুপস্থিত উত্তর |
--title |
_TITLE |
TgWitness witness |
প্রতিটি চ্যানেল পোস্টের প্রথম শব্দ |
--collector-fingerprint |
_COLLECTOR_FINGERPRINT |
– | প্রথম উত্তরে ভরসা করার বদলে কালেক্টর কী-কে পিন করুন। |
--proxy |
_PROXY |
সরাসরি | socks5://host:port অথবা http://host:port |
--bot-api |
_BOT_API |
https://api.telegram.org |
বট এপিআই ঠিকানা, যেমন একটি স্থানীয় বট এপিআই সার্ভার |
--data-dir |
_DATA |
witness-data |
সাক্ষী কী এবং জার্নাল |
--config |
_CONFIG |
– | উপরের যেকোনো বিকল্পসহ JSON ফাইল |
কলেক্টর ঠিকানা, টোকেন এবং চ্যানেল আসে --collector, --token অথবা --token-file, --bot-token অথবা --bot-token-file এবং --channel থেকে, অথবা _COLLECTOR, _TOKEN,
_TOKEN_FILE, _BOT_TOKEN, _BOT_TOKEN_FILE এবং _CHANNEL থেকে, যা প্রক্রিয়া তালিকা থেকে গোপনীয়তা লুকিয়ে রাখে।
একটি কনফিগ ফাইল আন্ডারস্কোরসহ অপশন নাম এবং texts ব্যবহার করে, যা চ্যানেলের পোস্টের শব্দগুলোকে প্রতিস্থাপন করে:
{"collector": "https://your-collector.example.org", "token_file": "witness-token.txt",
"bot_token_file": "bot-token.txt", "channel": "@your_witness_channel",
"interval": 5, "timeout": 30, "post": "changes", "title": "Partner witness",
"texts": {"ok": "journal head", "no_response": "no answer from the collector", "records": "records"}}
texts কী-গুলো: ok, key_changed, rollback, fork, invalid, no_response, collector,
records, head। কমান্ড লাইন পরিবেশের উপর, পরিবেশ ফাইলের উপর প্রাধান্য পায়।
অজানা অপশন বা টেক্সট কী-গুলো উপেক্ষা না করে একটি মেসেজ দেখিয়ে উইটনেসকে থামিয়ে দেয়।
শব্দচয়ন কখনো যাচাইকরণকে প্রভাবিত করে না: verify.py প্রতিটি পোস্টের শেষে স্বাক্ষরিত টোকেনটি যাচাই করে। --post changes বা problems ব্যবহারে, পোস্ট করা হয়নি এমন চেকগুলোও এখনও
উইটনেস জার্নালে থাকে এবং verify.py সেগুলোকে কখনোই পোস্ট করা হয়নি হিসেবে তালিকাভুক্ত করে; স্টার্ট রেকর্ড নীতিকে
নাম দেয়। প্রতিটি চেকই জার্নালে প্রদর্শিত হয়, তাই কম পোস্টের অর্থ কম স্বতন্ত্র
টেলিগ্রাম সময়, কম চেক নয়।
চ্যানেল ছাড়া সাক্ষী এখনও তার জার্নাল রাখে। সাক্ষীর কী ফিঙ্গারপ্রিন্ট (python -m tgwitness.witness fingerprint) অন্য কোথাও রাখুন।
যাচাই করুন#
সাক্ষী পক্ষের ক্ষেত্রে, এর জার্নাল রপ্তানি করুন:
python -m tgwitness.witness export --out witness.zip
# Docker (add -f deploy/compose/compose.witness.yaml on a witness server):
docker compose exec witness python -m tgwitness.witness export --out /witness/witness.zip
docker compose cp witness:/witness/witness.zip .
তারপর, যেকোনো জায়গায়, কালেক্টরের স্বাক্ষরিত ZIP এবং টেলিগ্রাম ডেস্কটপ থেকে রপ্তানি করা চ্যানেল (চ্যাট ইতিহাস রপ্তানি
→ JSON-এ result.json
দেয়) অথবা এর পাবলিক https://t.me/s/…
পৃষ্ঠা ব্যবহার করে:
python verify.py tgwitness-evidence.zip --fingerprint COLLECTOR_SHA256 \
--witness witness.zip --witness-fingerprint WITNESS_SHA256 --channel result.json
verify.py সাক্ষীর জার্নাল (চেইন এবং স্বাক্ষর) পরীক্ষা করে, তারপর যাচাই করে যে সাক্ষী যে প্রতিটি হেড দেখেছে তা রপ্তানি করা জার্নালের অংশ: সেই গণনার রেকর্ডের হ্যাশটি অবশ্যই ঠিক সেই হ্যাশটি হবে। যে হেডটি মিলবে না তা যাচাইকরণে ব্যর্থ হয় — সাক্ষী জার্নালটি দেখার পর জার্নালটি পরিবর্তিত হয়েছে। এটি রপ্তানির পর দেখা হেড, সাক্ষী যে অস্বাভাবিকতাগুলি রেকর্ড করেছে, ব্যর্থ উত্তরগুলি, সেই সময়কালগুলির মেলে যাওয়া চেকপয়েন্টগুলি এই রপ্তানিতে উপস্থিত আছে ("X থেকে Y পর্যন্ত সাক্ষী হয়েছে") এবং ফাঁকগুলিও রিপোর্ট করে। পরবর্তী চেকপয়েন্টগুলি সেই সময়কালগুলিকে প্রসারিত করে না।
ফলে সর্বশেষ মিলিত রেকর্ড নম্বর এবং মিলিত চেকপয়েন্টবিহীন পরবর্তী রেকর্ডগুলির সংখ্যা অন্তর্ভুক্ত থাকে। শুধুমাত্র সেই উত্তরগুলোই গণনা করা হয় যেগুলো এক্সপোর্টের নিজস্ব কী দ্বারা স্বাক্ষরিত: যে কী-তে সাক্ষী কখনোই দেখেননি, সেই কী দ্বারা স্বাক্ষরিত একটি এক্সপোর্ট 'সাক্ষীবিহীন' (not witnessed) হিসেবে রিপোর্ট করা হয়, এবং --fingerprint ছাড়া এর স্বাক্ষরকারী আনপিনড (unpinned) থাকে। --channel-এর সাথে প্রতিটি স্বাক্ষরিত পোস্টকে উইটনেস জার্নালের সাথে রেকর্ড অনুযায়ী মিলতে হবে: পরিবর্তিত পোস্টগুলো যাচাইকরণে ব্যর্থ হয়, অনুপস্থিত পোস্টগুলো তালিকাভুক্ত করা হয়। সরবরাহিত টেলিগ্রাম JSON এক্সপোর্টে থাকা একটি তারিখ সম্পাদনাযোগ্য মেটাডেটা, যা স্বাক্ষরিত উইটনেস টোকেনের বাইরে। টোকেনের মিল থাকা প্রকাশের তারিখকে প্রমাণীকরণ করে না; ফলাফল স্পষ্টভাবে রিপোর্ট করে যে প্রকাশের সময় যাচাইকরণ করা হয়নি।
সাক্ষীযুক্ত রপ্তানি সীমানা প্রয়োজন#
একটি হস্তান্তরের জন্য যা একটি সাক্ষীযুক্ত চূড়ান্ত রেকর্ড অন্তর্ভুক্ত করতে হবে, --require-witness যোগ করুন:
python verify.py tgwitness-evidence.zip --fingerprint COLLECTOR_SHA256 \
--witness witness.zip --witness-fingerprint WITNESS_SHA256 --require-witness
এর জন্য স্বাধীনভাবে সংরক্ষিত সাক্ষীর আঙ্গুলের ছাপ এবং এই রপ্তানির একেবারে শেষে একটি মিলিত চেকপয়েন্ট প্রয়োজন। শুধুমাত্র পূর্ববর্তী প্রিফিক্সকে অন্তর্ভুক্ত করে এমন একটি চেকপয়েন্ট অপর্যাপ্ত। সংগ্রহ স্থগিত করুন, সাক্ষীকে চূড়ান্ত অবস্থা পর্যবেক্ষণ করতে দিন, এবং আরও জার্নাল লেখার আগে রপ্তানি করুন; যদি জার্নাল পরিবর্তিত হয়, আরেকটি চেকপয়েন্ট সংরক্ষণ করুন এবং সেই অবস্থা রপ্তানি করুন। শুধুমাত্র পরবর্তী একটি চেকপয়েন্ট ছোট এক্সপোর্টের চূড়ান্ত হ্যাশ যাচাই করতে পারে না।
যখন --channel ফ্ল্যাগও সরবরাহ করা হয়, দাবি করা পোস্টগুলি অনুপস্থিত থাকা বা খালি মিল সেট এই কঠোর পরীক্ষাটি ব্যর্থ করে।
ফ্ল্যাগ ছাড়া, সাধারণ অখণ্ডতা পরীক্ষাগুলি অন্যথায় অক্ষত একটি আর্কাইভ প্রত্যাখ্যান না করেই পর্যবেক্ষণহীন রেকর্ডগুলি রিপোর্ট করে।
এই ফ্ল্যাগটি সরবরাহিত, পিন করা সাক্ষী রেকর্ডগুলোর সাথে সামঞ্জস্য বজায় রাখে। অপারেটরকে অবশ্যই সাক্ষীর স্বতন্ত্রতা প্রতিষ্ঠা করতে হবে এবং এর রেকর্ডগুলো আলাদাভাবে সংরক্ষণ করতে হবে। এটি বার্তার সত্যতা, সম্পূর্ণ সংগ্রহ বা স্বতন্ত্রভাবে পরিমাপিত রানটাইম প্রতিষ্ঠা করে না।
একজন সাক্ষী দেখায় যে সেই সময়ে কালেক্টর যা রিপোর্ট করেছিল এবং পরবর্তীতে রপ্তানিগুলো তার সাথে মেলে। এটি দেখায় না যে কালেক্টর টেলিগ্রামের সব ডেলিভারি রেকর্ড করেছিল, বা বার্তার বিষয়বস্তু সত্য। একই অপারেটর একই মেশিনে চালানো একটি সাক্ষী অন্য কেউ চালানো সাক্ষীর তুলনায় দুর্বল।
শুধুমাত্র গণসংখ্যা বৃদ্ধি করলে অনলাইনে শুধুমাত্র সংযোজনযোগ্য ধারাবাহিকতা প্রতিষ্ঠা করা যায় না: অফলাইন তুলনায় প্রতিটি সংরক্ষিত প্রিফিক্স হ্যাশকে সম্পূর্ণ কালেক্টর এক্সপোর্টের সাথে মিলিয়ে দেখতে হবে। উইটনেস ডাউনটাইম এবং প্রকাশনা ব্যর্থতার কারণে ইন্টারভালগুলো বাহ্যিক অ্যাঙ্করবিহীন হয়ে যায়। সংরক্ষিত উইটনেস জার্নালের বিরুদ্ধে অনুপস্থিত পোস্টগুলো রিপোর্ট করা যেতে পারে; একই অপারেটর দ্বারা নিয়ন্ত্রিত কোনো চ্যানেল বা সার্ভারই অপরিবর্তনীয় তৃতীয় পক্ষের আর্কাইভ নয়।