רוב הלקוחות מגיעים אלינו עם אותה בעיה: מערכות מעקב שרשרת האספקה שלהם הן רק מסד נתונים עם ממשק אינטרנט. הבעיה אינה טכנולוגית אלא ארכיטקטורת האמון: נתונים נרשמים על ידי צד אחד, ואחרים נאלצים להאמין להם. כאשר חמישה צדדים משלוש מדינות מעורבים בשרשרת, המודל הזה קורס. כאן בלוקצ'יין פותר בעיה אמיתית: הבטחת אי-שינוי של רשומות ואימות ציבורי ללא בורר מרכזי. לצוות שלנו ניסיון רב שנים בפיתוח בלוקצ'יין והוא סיפק למעלה מ-15 פרויקטים בתחום שרשרת האספקה. לדוגמה, רישום אירוע מעקב בודד על Polygon עולה כ-$0.005, שזה זול באופן שאין דומה לו מ-$5–10 ברשת הראשית של Ethereum. Polygon גובר על Ethereum ביותר מפי 1000 בעלות עסקה ובפי עשרות במהירות סופיות. גז לרישום ברשת פרטית של Hyperledger Fabric הוא שברירי סנט, למשל $0.0001 לעסקה.
כיצד בלוקצ'יין פותר את בעיית האמון בשרשרת האספקה
בחירת הרשת היא הצעד הראשון. עבור שרשראות אספקה ארגוניות עם קבוצת משתתפים ידועה, רשת מורשית כמו Hyperledger Fabric או Besu במצב IBFT מתאימה יותר. בלוקצ'יין ציבורי דרך L2 (Polygon, Base) מוצדק כאשר אימות ציבורי חשוב, למשל לסריקת QR על ידי צרכנים.
מה לאחסן On-Chain לעומת Off-Chain
הטעות העיקרית של פרויקטים מתחילים היא לנסות לאחסן הכל On-Chain. התוצאה: יקר, איטי, מיותר. כלל: רק גיבובי מסמכים, מזהי שחקנים (כתובות), חותמות זמן, סטטוסים (enum), ושורשי מרקל של קבוצות נתונים מאוחסנים On-Chain. אחסון Off-Chain כולל תמונות, תעודות PDF, קריאות חיישנים מפורטות, ואובייקטי JSON גדולים. קישור לאחסון (IPFS CID) וגיבוב התוכן נרשמים On-Chain. IPFS מספק אחסון מבוזר עם אימות גיבוב.
למה IPFS במקום הענן?
אחסון בענן קשור לספק יחיד—נקודת כשל יחידה. IPFS מבוזר: נתונים משוכפלים על פני צמתים רבים, נגישים לפי גיבוב, ושלמותם מאומתת קריפטוגרפית. עבור שרשראות אספקה, זה מבטיח שאף משתתף לא יכול לשנות בדיעבד את ההיסטוריה של מוצר.// Событие трекинга: лёгкое on-chain, детали в IPFS struct TrackingEvent { bytes32 batchId; // ID партии/лота bytes32 dataHash; // keccak256 от полного JSON события string ipfsCid; // CID полных данных в IPFS address actor; // кто записывает (верифицированный участник) EventType eventType; // PRODUCED, SHIPPED, RECEIVED, INSPECTED, SOLD uint256 timestamp; bytes32 locationHash; // хеш от GPS координат (для приватности) } enum EventType { PRODUCED, SHIPPED, RECEIVED, INSPECTED, CERTIFIED, SOLD } mapping(bytes32 => TrackingEvent[]) public batchHistory; mapping(bytes32 => bool) public authorizedActors; event BatchEvent( bytes32 indexed batchId, EventType indexed eventType, address indexed actor, bytes32 dataHash, string ipfsCid ); function recordEvent( bytes32 batchId, bytes32 dataHash, string calldata ipfsCid, EventType eventType ) external { require(authorizedActors[keccak256(abi.encode(msg.sender, eventType))], "Not authorized for this event type"); TrackingEvent memory evt = TrackingEvent({ batchId: batchId, dataHash: dataHash, ipfsCid: ipfsCid, actor: msg.sender, eventType: eventType, timestamp: block.timestamp, locationHash: bytes32(0) }); batchHistory[batchId].push(evt); emit BatchEvent(batchId, eventType, msg.sender, dataHash, ipfsCid); } ניהול גישת משתתפים עם DID
בשרשרת אספקה, ישנם כמה סוגי שחקנים: יצרן, לוגיסטיקאי, מכס, קמעונאי, מפקח. // Событие трекинга: лёгкое on-chain, детали в IPFS struct TrackingEvent { bytes32 batchId; // ID партии/лота bytes32 dataHash; // keccak256 от полного JSON события string ipfsCid; // CID полных данных в IPFS address actor; // кто записывает (верифицированный участник) EventType eventType; // PRODUCED, SHIPPED, RECEIVED, INSPECTED, SOLD uint256 timestamp; bytes32 locationHash; // хеш от GPS координат (для приватности) } enum EventType { PRODUCED, SHIPPED, RECEIVED, INSPECTED, CERTIFIED, SOLD } mapping(bytes32 => TrackingEvent[]) public batchHistory; mapping(bytes32 => bool) public authorizedActors; event BatchEvent( bytes32 indexed batchId, EventType indexed eventType, address indexed actor, bytes32 dataHash, string ipfsCid ); function recordEvent( bytes32 batchId, bytes32 dataHash, string calldata ipfsCid, EventType eventType ) external { require(authorizedActors[keccak256(abi.encode(msg.sender, eventType))], "Not authorized for this event type"); TrackingEvent memory evt = TrackingEvent({ batchId: batchId, dataHash: dataHash, ipfsCid: ipfsCid, actor: msg.sender, eventType: eventType, timestamp: block.timestamp, locationHash: bytes32(0) }); batchHistory[batchId].push(evt); emit BatchEvent(batchId, eventType, msg.sender, dataHash, ipfsCid); } פשוט אינו מתאים—נדרשת מערכת מבוססת תפקידים עם האצלה. W3C DID Core הוא תקן לזהות מבוזרת. לכל משתתף יש DID המקושר לכתובות החוזה החכם שלו. אימות משתתף (KYB) מתבצע Off-Chain דרך מאמתים מוסמכים המנפיקים אישורים ניתנים לאימות (VC).
// Верификация VC при регистрации участника import { Resolver } from 'did-resolver' import { getResolver as ethrResolver } from 'ethr-did-resolver' import { verifyCredential } from 'did-jwt-vc' async function verifyParticipantCredential( vcJwt: string, participantAddress: string ): Promise<boolean> { const resolver = new Resolver({ ...ethrResolver({ infuraProjectId: process.env.INFURA_ID }) }) const result = await verifyCredential(vcJwt, resolver) // Проверяем, что VC выдан аккредитованным верификатором const trustedIssuers = await getTrustedIssuers() // из смарт-контракта if (!trustedIssuers.includes(result.issuer)) { return false } // Проверяем, что VC относится к данному адресу return result.verifiableCredential.credentialSubject.ethereumAddress .toLowerCase() === participantAddress.toLowerCase() } גישה מבוססת תפקידים עם חלונות זמן
משתתף עשוי לקבל זכות לרשום אירועים רק בתקופה מסוימת (למשל, זמן מעבר מטען):
struct ActorPermission { bytes32 role; // PRODUCER_ROLE, SHIPPER_ROLE, etc. uint256 validFrom; uint256 validUntil; bytes32[] allowedBatches; // пустой массив = все партии } mapping(address => ActorPermission[]) public permissions; function isAuthorized( address actor, bytes32 role, bytes32 batchId ) public view returns (bool) { ActorPermission[] storage perms = permissions[actor]; for (uint i = 0; i < perms.length; i++) { if (perms[i].role == role && perms[i].validFrom <= block.timestamp && perms[i].validUntil >= block.timestamp) { if (perms[i].allowedBatches.length == 0) return true; for (uint j = 0; j < perms[i].allowedBatches.length; j++) { if (perms[i].allowedBatches[j] == batchId) return true; } } } return false; } כיצד לשלב IoT עם בלוקצ'יין?
נתוני חיישנים חייבים להגיע On-Chain באופן אוטומטי ובלתי ניתן לשינוי. זו בעיה ארכיטקטונית: מכשיר IoT אינו יכול לחתום על עסקאות Ethereum ישירות (אין לו RAM או סוללה לקריפטוגרפיה ברמת EVM). אנו משתמשים בתבנית Gateway + Oracle: שער קצה אוסף נתוני חיישנים, חותם עליהם, מפרסם ל-IPFS, ושירות אורקל שולח את העסקה לחוזה החכם.
# Oracle service: верификация и запись sensor события from web3 import Web3 from eth_account import Account import ipfshttpclient async def process_sensor_reading(gateway_id: str, payload: dict, signature: str): # 1. Верифицируем подпись gateway message = encode_defunct(text=json.dumps(payload, sort_keys=True)) recovered = w3.eth.account.recover_message(message, signature=signature) gateway_address = await get_registered_gateway(gateway_id) if recovered.lower() != gateway_address.lower(): raise ValueError("Invalid gateway signature") # 2. Публикуем в IPFS async with ipfshttpclient.connect() as ipfs: cid = ipfs.add_json(payload) # 3. Записываем on-chain data_hash = Web3.keccak(text=json.dumps(payload, sort_keys=True)) tx = tracking_contract.functions.recordSensorEvent( payload['batch_id'].encode(), data_hash, cid, EventType.SENSOR_READING ).build_transaction({ 'from': oracle_account.address, 'nonce': w3.eth.get_transaction_count(oracle_account.address), 'maxFeePerGas': await get_gas_price(), }) signed = oracle_account.sign_transaction(tx) tx_hash = w3.eth.send_raw_transaction(signed.rawTransaction) return tx_hash.hex() לדרישות אמון גבוהות, אנו משתמשים ב-HSM (מודול אבטחת חומרה) ישירות במכשיר. Microchip ATECC608 הוא שבב זול עם זוג מפתחות ECC שלא ניתן לחילוץ. המכשיר חותם על נתונים עם מפתח המוגן פיזית מפני פשרה.
דוגמה: שרשרת אספקה פרמצבטית
שקול שרשרת אספקה פרמצבטית (תקן FDA DSCSA דורש מעקב אלקטרוני). אירועים עיקריים:
- אירוע 1: ייצור — רישום מזהה אצווה, תאריך, הרכב, גיבוב CoA. נוצר קוד QR עם batchId.
- אירוע 2: משלוח — הלוגיסטיקאי סורק את ה-QR, רושם מזהה מוביל, מספר מעקב, טווח טמפרטורות.
- אירוע 3: שחרור ממכס — רישום הצהרה, סטטוס, מזהה מפקח.
- אירוע 4: קבלה — תאריך, בדיקה פיזית, אי-התאמות. אימות גיבוב.
- אירוע 5: מכירה לצרכן — הצרכן סורק את ה-QR ורואה את ההיסטוריה המלאה.
איך אנחנו עושים את זה: 5 שלבים
- ניתוח תהליכים עסקיים — זיהוי אירועי מפתח, תפקידי משתתפים, ונקודות הזנת נתונים.
- עיצוב מודל On/Off-chain — קביעה מה לאחסן בבלוקצ'יין לעומת IPFS.
- פיתוח חוזה חכם — יישום מעקב, מערכת תפקידים, ובקרת גישה.
- שילוב IoT ו-ERP — הגדרת שער, אורקל, ו-API עבור ERP/WMS.
- פיילוט והשקה — בדיקה עם נתונים אמיתיים, הדרכת משתתפים.
בחירת רשת
| פרמטר | L2 ציבורי (Polygon/Base) | Hyperledger Fabric | Besu (IBFT) |
|---|---|---|---|
| אימות ציבורי | כן | לא | לא |
| עלות לכתיבה | ~$0.001–$0.01/עסקה | כמעט 0 | כמעט 0 |
| מהירות סופיות | 2–5 שניות | < 1 שנייה | 2–5 שניות |
| בקרת גישה | חוזים חכמים | ערוץ/MSP מקורי | חוזים חכמים |
| דרישות רגולטוריות | בלוקצ'יין ציבורי | רשת פרטית | רשת פרטית |
שלבי פיתוח
| שלב | משך | תוצאה |
|---|---|---|
| עיצוב | 2–3 שבועות | ניתוח תהליכים עסקיים, מודל נתונים On/Off-chain |
| חוזים חכמים | 3–4 שבועות | חוזי מעקב, מערכת תפקידים, בדיקות |
| אורקל + IoT | 3–4 שבועות | שילוב שער, שירות אורקל, צינור IPFS |
| API & לוח מחוונים | 3–4 שבועות | REST/GraphQL API, פאנל ניהול, מאמת צרכני |
| שילוב ופיילוט | 2–4 שבועות | שילוב ERP/WMS, פיילוט |
השלב הגוזל ביותר הוא שילוב עם מערכות ERP מדור קודם של משתתפים, לא פיתוח בלוקצ'יין.
מה כלול
חוזים חכמים: מעקב אירועים, מערכת תפקידים, בקרת גישה. צד אחורי: API לשילוב ERP/WMS, שירות אורקל לעיבוד נתוני IoT. לוח מחוונים: פאנל ניהול ומודול אימות מוצר לצרכן. תיעוד: דיאגרמת ארכיטקטורה, מפרט API, מדריך פריסה. הדרכה: הדרכה למשתתפי מפתח בשרשרת. תמיכה: שירות אחריות והרחבה אופציונלית.
צרו קשר כדי להעריך את הפרויקט שלכם. הזמינו פיתוח מעקב שרשרת אספקה מקצה לקצה.







