במהירות הבזק – פרק א'

במהירות הבזק – פרק א' – כיצד מתבצעות טרנזקציות ברשת הברק

הסבר ממוקד על איך המימוש של רשת הברק עובד. נדרש ידע קודם של: UTXO, Bitcoin Script, and digital signatures.

 

תרגום מאנגלית של המאמרים:

https://medium.com/swlh/till-its-lightning-fast-uncover-the-development-of-the-lightning-network-fbd01bc0ea80

https://medium.com/@yyforyongyu/till-its-lightning-fast-uncover-the-lightning-network-transactions-f3180e467857

גרסה מתורגמת של שני הפרקים לעברית רב-מגדרית ניתן למצוא כאן.

פיתוח רשת הברק

הרעיון של רשת הברק הוא ליצור מערכת שתפעל לצד רשת הביטקוין. בעוד שהטרנזקציות בביטקוין חייבות להיות מוגבלות בזמן ובגודל, כלומר שכ-2MB (לערך) יישלחו כל 10 דקות, רשת הברק פורצת את המגבלות הללו ע"י העברת ביטקוינים לרשת שלה וסירקולציה שלהם בתוך הרשת תחת מגבלות אחרות.

אם שני משתתפים מעוניינים להצטרף לרשת הברק, הצעד הראשון עבורם הוא ליצור כתובת מרובת-חתימות (multisig) עבור חשבון משותף, או במילים אחרות לפתוח ערוץ בינם. מהרגע שנפתח הערוץ, הוא ינוצל להעברת כסף בתוך הרשת. אם מאיזושהי סיבה צריך למשוך את הכסף מהערוץ לרשת הביטקוין, המשתתפים יכולים לסגור את הערוץ בשיתוף פעולה. הכסף זורם מרשת הביטקוין לרשת הברק אם אנשים מחליטים לפתוח ערוצים, והוא אף פעם לא צריך לחזור לרשת הביטקוין אלא אם כן אנשים רוצים לסגור את הערוצים שלהם. באופן כללי, שני המקרים הצפויים לטרנזקציות "בין שכבות" הן פתיחת ערוץ וסגירת ערוץ, פרט למקרה יוצא הדופן: כשאחד המשתתפים הפסיק להגיב או מנסה לפעול באופן זדוני – שאר המשתתפים יכולים באופן חד צדדי, ללא שיתוף פעולה איתו, לסגור את הערוצים מולו.

בניית חשבון משותף

כדי להשתמש ברשת הברק, הצעד הראשון הוא להעביר אליה כמה ביטקוין. המשתתפים ייצרו כתובות מרובות-חתימות שאליהן ישלחו את הכספים. לדוגמא, אליס ובוב מחליטים לפתוח ערוץ עם 1.5 ביטקוין, שאליו אליס תתרום 0.5 ביטקוין ובוב יתרום 1 ביטקוין.

כל אחד מהם ייצור טרנזקציה כדי לתקצב את הערוץ, ואת הכסף שנעול בכתובת הזו לא ניתן להוציא אלא אם כן שניהם מסכימים.

ה-ID של הטרנזקציה וה-Output Number של הכניסות הושמטו לצורך ההדגמה.

ה-ID של הטרנזקציה וה-Output Number של הכניסות הושמטו לצורך ההדגמה.

נתייחס עכשיו למקרים הבאים:

  1. מה קורה אם אחד המשתתפים מסרב לשתף פעולה?
  2. מה קורה אם אליס, בוב, או שניהם ביחד, מחליטים לסגור את הערוץ ולקבל את כספם בחזרה?
  3. מה אם צריך לעדכן את המאזן? נניח אליס משלמת לבוב 0.1 ביטקוין עבור משהו שהיא קונה מבוב?


לפני שנתמודד עם הנושאים הללו, חשוב להדגיש שרשת הברק צריכה להיות מתוכננת באופן המאפשר אבטחה תוך שמירה על ביזור. היא צריכה להישאר Trustless כמו רשת הביטקוין – ולא לסמוך על היושרה של אף אחד או אף ארגון כדי להעביר כסף בהצלחה. לשם כך, נדרשת תכנית מורכבת באמצעות ה-Bitcoin Script.
בניגוד לרשת הביטקוין המסתמכת על כוח חישוב, רשת הברק תאבטח את עצמה באמצעות עונשים מובנים בתוך המערכת.

בואו נפתור תחילה את בעיית התקצוב הראשוני של הערוץ. נזכור שבשכבה הראשונה, רשת הביטקוין, טרנזקציית ביטקוין מתבצעת בשלושה שלבים:

  1. יצירת הטרנזקציה
  2. חתימה על הטרנזקציה – או בניסוח טכני: צירוף "סקריפט שחרור נעילה" (Unlocking script).
  3. שידור הטרנזקציה

האם אנחנו יכולים לפתח מנגנון חכם בין השלבים הללו?

תקצוב ללא חתימה

אליס ובוב יכולים ליצור את הטרנזקציות לעיל בלי לחתום עליהן. המטרה של השארת הטרנזקציות לא חתומות היא כדי לאפשר את ביטול התהליך במקרה שאחד הצדדים מסרב לשתף פעולה. מכיוון שהטרנזקציות לא חתומות, אף אחד לא מחויב לשום דבר, כלומר שום נזק לא יכול להיגרם באותו הרגע. באמצעות התייחסות ל-Outputים של הטרנזקציות הלא חתומות, אליס ובוב יכולים ליצור מראש טרנזקציה חדשה כדי להחליט לאן יגיעו הכספים שינעלו בכתובת מרובת-החתימות (multisig). במצב הנוכחי, הטרנזקציה הזו צריכה לתת 0.5 ביטקוין לאליס, ו-1 ביטקוין לבוב.

מהרגע שהטרנזקציה הזו נוצרה, שתי שאלות צריכות להישאל:

  1. האם הם צריכים לחתום על הטרנזקציה החדשה? כן. ברגע זה אף אחד לא מסכן שום כסף. אם אליס חתמה על הטרנזקציה אבל בוב מסרב, היא יכולה מייד לעצור את התהליך בלי לאבד שום דבר, ולהיפך.
  2. האם הם צריכים לשדר את הטרנזקציה החדשה? לא. המטרה של הטרנזקציה הזו היא למנוע איבוד כספים במקרה שאחד המשתתפים לא מגיב. כל עוד הצד השני מגיב, וכל עוד המשתתפים לא מעוניינים לסגור את הערוץ, הטרנזקציה הזו לעולם לא תשודר.

מה שצריכה להיחתם ולהתפרסם במקום זה, זוהי טרנזקציית התקצוב המקורית, ברגע שלאליס ולבוב יש עותק חתום של הטרנזקציה החדשה. הטרנזקציה החדשה מתפקדת בדומה לעירבון במקרה של שכירת דירה – נותנים אותה כדי להראות מחויבות לחוזה, והיא מאפשרת לקבל פיצוי במקרה שהחוזה הופר. לכן לטרנזקציה זו קוראים בדר"כ בשם "טרנזקציית ההתחייבות" (Commitment Transaction).

לסיכום, התהליך שבו אליס ובוב פותחים ערוץ באופן מאובטח הוא כדלקמן:

  1. אליס ובוב, כל אחד בנפרד, יוצרים טרנזקציית תקצוב מבלי לחתום עליה.
  2. אליס ובוב יוצרים וחותמים על טרנזקציית התחייבות המבוססת על טרנזקציות התקצוב. לדוגמא: אליס יוצרת את טרנזקציית ההתחייבות, חותמת עליה, שולחת לבוב, ובוב בודק אותה ושולח את חתימתו חזרה לאליס. או ששניהם בונים את טרנזקציית ההתחייבות בנפרד ושולחים אחד לשני רק את החתימות. בכל מקרה, התוצאה היא ששניהם מחזיקים באותה טרנזקציית התחייבות חתומה.
  3. אליס ובוב משדרים את טרנזקציות התקצוב שלהם.

ברגע שטרנזקציות התקצוב עברו confirmation, הערוץ נחשב "ממומן" והם צריכים למצוא דרך לשלוח דרכו ביטקוין. אבל לפני שאנחנו משחקים עם ה-Bitcoin Script כדי לאפשר עדכוני מאזן בערוץ, עלינו לשאול שאלה קריטית: איך יוצרים בפועל את טרנזקציית התקצוב?

הערת מתרגם: גם המקרה שבו שניהם מחזיקים בטרנזקציית ההתחייבות הנ"ל חתומה, אבל רק צד אחד משדר את טרנזקציית התקצוב שלו, הוא בעייתי – כי טרנזקציית ההתחייבות מצביעה על שני Inputים, ושניהם צריכים להיות ברשת הביטקוין כדי שהיא תתקבל. גם בעיה זו נפתרת ע"י תקצוב חד צדדי.

האלטרנטיבה – תקצוב חד צדדי

במקום תקצוב דו צדדי כמו שהוצג קודם, המימוש בפועל של רשת הברק משתמש בתקצוב חד צדדי עם טוויסט לגבי האופן שבו טרנזקציית התקצוב נחתמת ומשודרת. בשלב הראשון, כל משתתף יכול להיות ה-"מתקצב". אם למשל אליס מחליטה לקנות משהו מבוב, היא יכולה להתייחס לתשלום כאל התקציב שבוב אמור לשים בחלק שלו בפתיחת הערוץ. בהמשך, כשבוב יבצע קניות מאחרים, הוא יוכל להשתמש בכסף בערוץ בלי שום אינטראקציה עם רשת הביטקוין (במימוש הסופי). ככל שמספר הערוצים עולה, לכל משתתף יש איזשהו מאזן באיזשהו ערוץ שפתחו מולו, באופן דומה למצב שבו הקמת הערוצים הייתה מתבצעת באופן דו צדדי.

אם אליס הייתה המתקצבת הראשונית בתקצוב חד צדדי, זה קריטי לוודא שאם בוב מפסיק להגיב, אליס עדיין תוכל לקבל חזרה את התקצוב שלה.

כשבונים טרנזקציית ביטקוין, ה-Inputים שלה צריכים להפנות ל-ID של טרנזקציות קודמות ול-Output Number שלהן. לפיכך, אליס יכולה לבנות מראש את כל טרנזקציית התקצוב מבלי לשדר אותה, ולשתף עם בוב רק את ה-ID וה-Output Number. כשבוב מקבל את המידע, מכיוון שהוא לא קיבל מאליס את החתימות הדרושות לטרנזקציה, הוא לא יכול לעשות שום דבר עם המידע חוץ מאשר ליצור טרנזקציית התחייבות, שתיתן לאליס חזרה את הכסף. סיכום הצעדים הוא כדלקמן:

  1. אליס יוצרת את טרנזקציית התקצוב, חותמת עליה, ומשתפת עם בוב את ה-ID וה-Output Number של הטרנזקציה (בלי הטרנזקציה עצמה ובלי החתימות שלה).
  2. אליס ובוב יוצרים וחותמים את טרנזקציית ההתחייבות, על בסיס ה-ID וה-Output Number של טרנזקציית התקצוב. שימו לב שטרנזקציית התקצוב שמה את הכסף של אליס בכתובת מרובת-חתימות (multisig), שדורשת את החתימות של שניהם כדי לשלוח את הכסף חזרה לאליס באמצעות טרנזקציית ההתחייבות.
  3. אליס משדרת את טרנזקציית התקצוב. בנקודה זו, אם בוב מפסיק להגיב, אליס יכולה לשדר את טרנזקציית ההתחייבות כדי לקבל את כספה חזרה.

טרנקציית התקצוב של אליס נשארת ללא שינוי, אבל היא לא תשדר אותה ולא תשתף עם בוב את חתימתה, אלא רק תשלח לו את ה-ID של הטרנזקציה (00) ואת ה-Output Number של הטרנזקציה (0).

שיטת התקצוב החד צדדי הזו מסירה את הסיכון שיאבדו כספים למתקצב, תודות לאופן שבו ביטקוין מבזבז UTXOים בטרנזקציות שלו. למרות שאפשר להרחיב את השיטה לתקצוב דו צדדי, פרוטוקול רשת הברק בפועל מעדיף את שיטת התקצוב החד צדדי. הסיבה לכך היא כנראה מכיוון שדרושה פחות תקשורת בין המשתתפים, למרות שזה לא מוסבר באופן מפורש. לגבי תקצוב דו צדדי, ישנו דיון מתמשך לגבי איך ניתן לממש אותו.

הערת מתרגם: נכון לכתיבת מילים אלו יש מימוש שאולי תומך ב-dual-funding כזה, בשם nolooking (וגם כאפליקציה ל-Umbrel), אבל לא ניסיתי אותו בעצמי.

עדכון המאזן בערוץ

כעת יש לנו חשבון כספי משותף שניתן לסגור ולסיים, אבל מה לגבי שינוי המאזן בחשבון? אליס שמה בחשבון 0.5 ביטקוין לפתיחת הערוץ, והיא רוצה לשלוח 0.1 ביטקוין לבוב בתמורה ללפטופ שלו – איך הם יעשו זאת ברשת הברק?

הפתרון הטריוויאלי הוא שאליס ובוב יכולים ליצור טרנזקציות חדשות כדי לשקף את המאזן האחרון בינם.

מבחינת אליס, היא תיצור את הטרנזקציה הבאה, תחתום עליה ותשלח אותה לבוב. מכיוון שהטרנזקציה חתומה כבר ע"י אליס, בוב יכול להוסיף את החתימה שלו ולשדר את הטרנזקציה מתי שירצה.

באופן סימטרי, בוב יחתום על הטרנזקציה וישלח אותה לאליס, כדי שהיא תוכל לחתום ולשדר אם היא רוצה (אם היא רוצה לסגור את הערוץ מגיע לה לקבל רק 0.4 ביטקוין). כרגע, לשני המשתתפים יש שתי טרנזקציות חתומות במקביל. יחד, ראינו 5 טרנזקציות עד כה:

  1. טרנזקציית התקצוב מאליס, שכבר שודרה.
  2. טרנזקציית ההתחייבות שאליס מחזיקה, שנותנת לה את הכסף חזרה. נקרא לה: TX A1.
  3. בוב גם מחזיק בעותק של טרנזקציית ההתחייבות. נקרא לו: TX B1.
  4. הטרנזקציה החדשה של אליס, שנותנת לאליס 0.4 ביטקוין, ולבוב 0.1 ביטקוין. נקרא לה: TX A2.
  5. לבוב גם יש עותק של הטרנזקציה החדשה. נקרא לו: TX B2.

הטרנזקציות שהמשתתפים מחזיקים ויכולים לשדר, בפשטות נראות ככה:

כל ארבע הטרנזקציות הן תקינות לפני ששודרו לרשת הביטקוין, ויש להן סיכוי שווה להתקבל ע"י כורים אם משדרים אותן באותו רגע. אם זה נשמע לכם מבלבל, דמיינו את ביטקוין בתור "הדוד תום" שעובד כמנהל חשבונות ומעדכן ספר חשבונות על פי הטרנזקציה הראשונה שהוא שומע, ומתעלם מהטרנזקציות הבאות.

במקרה הנוכחי, אם נתייחס לאליס ובוב כאל אנשים רציונליים (מבחינה כלכלית), האינטרס של אליס הוא לשדר את TX A1 כדי לגנוב את ה-0.1 ביטקוין שהיא הבטיחה לשלם לבוב. מבחינת בוב, עדיף לו לשדר את TX B2 מכיוון שהוא יקבל 0.1 ביטקוין (עדיף על כלום). אם שתי הטרנזקציות משודרות באותו זמן, מדובר רק בסיכויים של 50:50 שבוב יקבל את מה שמגיע לו – וזה בלתי מתקבל על הדעת.

איך נפתור את הבעיה? איך אנחנו יכולים לוודא שכל המשתתפים תמיד משדרים את הטרנזקציה האחרונה ולא טרנזקציות ישנות?

לפני שנתקדם הלאה, ניזכר בסוגי הטרנזקציות פה, מכיוון שזה עלול להיות מבלבל כשמסתכלים על כל הטרנזקציות שהתרחשו ברשת הברק.

  1. אם לטרנזקציה אין שום קשר לרשת הברק, כלומר היא מתרחשת רק ברשת הביטקוין, קוראים לה טרנזקציית "שכבה ראשונה".
  2. אם הטרנזקציה מכניסה כסף מרשת הביטקוין לרשת הברק, כלומר פותחת ערוץ, או שהיא מוציאה כסף מרשת הברק לרשת הביטקוין, כלומר סוגרת ערוץ – קוראים לה טרנזקציה "בין שכבות", מכיוון שהיא מבצעת אינטראקציה בין שתי הרשתות.
  3. אם הטרנזקציה נועדה להישאר ברשת הברק, היא נקראת טרנזקציית "שכבה שנייה". למרות שאם טרנזקציית שכבה שנייה משודרת לרשת הביטקוין (בטעות, בזדון, או כתגובה לצד השני), היא הופכת לטרנזקציית בין-שכבות. המהות של רשת הברק היא לוודא שטרנזקציות שכבה שנייה לא יהיה ניתן למחוק.

בעצם, טרנזקציות שנוצרו ברשת הברק ניתן לשדר באופן לגיטימי לרשת הביטקוין, כלומר טרנזקציות שכבה שנייה הן טרנזקציות שכבה ראשונה עם ייחוד מסויים. רשת הביטקוין היא איטית ורשת הברק צריכה להיות מהירה, ולכן התכנית של רשת הברק נועדה לגרום לכך שהשימוש בטרנזקציות שכבה שנייה כטרנזקציות שכבה ראשונה (כלומר, שידורן לרשת הביטקוין) יהיה נדיר ככל האפשר.

שכלול סקריפט הנעילה (Locking Script)

קודם לכן, כל סקריפטי הנעילה המעורבים השתמשו רק בריבוי-חתימות. כעת נראה אם אנחנו יכולים למצוא דרך בטוחה לעדכן את המאזנים ע"י שינוי ה-Outputים שבטרנזקציות שאנחנו בונים. המטרה היא פשוטה, נממש עונש נגד רמאים, שמוגדרים כמי שמנסה לשדר טרנזקציה ישנה. מבלי לצלול לדרכים השונות בהן ניתן להעניש משתתפים, מה שרשת הברק עושה זה לגרום לרמאי לאבד את כספו ברגע שהצד השני שם לב לניסיון ההונאה, בתוך פרק זמן מוגבל (בתוכנות ארנק רגילות זה לא יכול לקרות אלא אם כן יש באג חמור – אבל מי שרוצה לפעול במכוון באופן זדוני יכול לכתוב תוכנה כזו).

בחזרה לדוגמא שלנו, אם אליס משדרת את TX A1, שנותנת לה 0.5 ביטקוין, אנחנו רוצים להכניס בתכנית מנגנון שיאפשר לבוב מספיק זמן כדי לשים לב לזה ולפעול כדי לקחת לאליס, כעונש, את כל הכסף.

וכאן נכנסת לתמונה "נעילת זמן" (Timelock), באופן ספציפי, OP_CHECKSEQUENCEVERIFY. נעילת זמן בעצם מתחילה ספירה לאחור מהרגע שטרנזקציה משודרת (או יותר נכון, מהרגע שהכורים מוסיפים אותה לבלוק), ונועלת את הכספים עד אשר תקופת הזמן המצויינת חלפה. אם טרנזקציה שכוללת נעילת זמן של 40 יום שודרה היום, לא ניתן להוציא ממנה כספים עד שחלפו 40 יום. אם היא תשודר רק בעוד שנה מהיום, לא ניתן יהיה להוציא ממנה כספים עד שתחלוף שנה + 40 יום (מהיום). נעילת הזמן היחסית הזו יכולה לעזור לנו בבניית סקריפט נעילה חדש:

  1. אליס יכולה לשדר את TX A1 כדי לקבל את כספה חזרה אם בוב מפסיק להגיב.
  2. היא צריכה לחכות שבועיים לפני שתוכל לבזבז את ה-UTXO של TX A1 אם הוא משודר.
  3. אם בוב דווקא מגיב ומגלה שאליס שידרה את TX A1, הוא יכול לקחת את כל הכסף מיד, כעונש לאליס.

טרנזקציית ההתחייבות TX A1 המשודרגת נראית ככה:

אם אליס מנסה ליצור טרנזקציה בין-שכבות על בסיס TX A1, היא לא תוכל לקבל את הכסף עד אשר חלפו שבועיים, שנאכפים ע"י נעילת הזמן (Timelock). באותו זמן, אם בוב (או ליתר דיוק, מחשב הצומת של בוב) מגלה ש-TX A1 שודרה, הוא יכול מיד לבזבז את ה-0.5 ביטקוין שיש בה (מחשב הצומת של בוב יעביר את הסכום לארנק הפרטי של בוב).

התכנית הנ"ל מוודאת שאם טרנזקציה ישנה שודרה, הכסף של אליס יילקח ממנה כעונש. מצד שני, התכנית נותנת יותר מדי כוח לבוב, שבאמצעות החתימה שלו יכול לקחת את כל הכסף, מה שמעודד אותו להפוך להיות האיש הרע (כשהאוהדים שלך הופכים לשונאים שלך). הכוונה המקורית במתן אפשרות לאליס לקבל חזרה את ה-0.5 ביטקוין שלה, היא כדי להגן עליה במקרה שבוב מפסיק להגיב. לעומת זאת, לבוב יש עכשיו מוטיבציה לרמות את אליס כדי שתשדר את הטרנזקציה, בכך שבכוונה יפסיק להגיב – ואז כשאליס תשדר את הטרנזקציה, בוב מיד ייקח את כל הכסף.

עלינו לשכלל את התכנית.

הרבה מפתחות, הרבה בלבול – ההיסטוריה של RSMC

כשאנו מדברים על "החתימה של אליס", אנחנו בעצם מתכוונים לחתימה שנוצרה ע"י אחד המפתחות שאליס שולטת בהם. הרעיון של "חתימה של אליס" הוא למעשה חתימה באמצעות מפתח פרטי. מצד שני, אליס יכולה ליצור כמה מפתחות פרטיים שהיא צריכה, ולא רק אחד. היכולת הזו חשובה כי היא מאפשרת לבטל את היתרון של בוב בשיטה הקודמת.

במקום לבקש רק את החתימה של בוב בסקריפט הנעילה, נבקש ריבוי-חתימות (multisig) כדי למנוע מבוב לגנוב את הכסף. כשהמשתתפים מסכימים לעדכן את המאזנים ע"י יצירת טרנזקציות חדשות, הם ישתפו בינם את המפתחות הפרטיים בריבוי-החתימות של הטרנזקציות הישנות, כלומר יאפשרו לצד השני לשחרר נעילות מסוימות שהוא לא יכול היה לשחרר קודם.

לצורך ההדגמה, ניתן למפתחות הפרטיים שמות כדי לעקוב אחריהם. בנקודת ההתחלה, אליס תיצור ארבעה מפתחות פרטיים: A1RickBatman, ו-Tom. בוב, בהתאמה, ייצור מפתחות פרטיים: B1MortyRobin ו-Jerry.

מצד אליס, הטרנזקציה TX A1 נראית ככה:

מהצד של בוב, הטרנזקציה TX B1 היא יותר פשוטה, מכיוון שאף פעם אין לו אינטרס לשדר אותה (היא נותנת את כל הכסף לאליס):

ע"י שימוש בריבוי-חתימות ב-TX A1, התבטל היתרון של בוב. אם לא היו עדכונים למאזן, כלומר TX A2 ו-TX B2 עדיין לא נוצרו, הכסף של אליס נשאר מאובטח אפילו אם בוב מפסיק להגיב (בטעות או בזדון) – מכיוון שלבוב אין את המפתח Rick.

אם הם רוצים עדכונים נוספים של המאזנים, הם צריכים ליצור טרנזקציות חדשות עם סקריפט נעילה דומה. במהלך היצירה של הטרנזקציות החדשות, הם גם יחליפו ביניהם את המפתחות הפרטיים שהשתמשו בהם בטרנזקציות הקודמות. במקרה שלנו, אליס תשלח לבוב את המפתח הפרטי Rick כאשר היא יוצרת את TX A2. צעד זה משנה את המשחק, מכיוון שהוא מבטל לחלוטין כל אינטרס של אליס לנסות לרמות ולשדר את TX A1 – אם היא תעשה זאת היא תאבד את כל כספה לבוב מכיוון שבוב ישתמש ב-Rick וב-Morty כדי לשחרר את סקריפט הנעילה.

מהצד של אליס, טרנזקציית TX A2 תראה כך:

ומהצד של בוב, טרנזקציית TX B2 תראה כך:

אם אליס תחליט ליצור עדכון נוסף במאזן עבור תשלום לבוב של 0.2 ביטקוין, הצעדים יהיו כדלקמן:

  1. ליצור טרנזקציות חדשות. גם אליס וגם בוב ייצרו מפתחות חדשים כדי ליצור טרנזקציות דומות לאיור האחרון. הטרנזקציות החדשות, TX A3 ו-TX B3, ייתנו לאליס 0.2 ביטקוין ולבוב 0.3 ביטקוין.
  2. לאחר שיתוף הטרנזקציות החדשות, הם יחליפו ביניהם את המפתחות הפרטיים הישנים. אליס תיתן לבוב את המפתח הפרטי Batman, ובוב ייתן לאליס את המפתח הפרטי Jerry. באופן זה, אף אחד לא ירצה לשדר את הטרנזקציות הישנות, מכיוון שזה יאפשר לצד השני לקחת מייד את כל הכסף.

כמו קודם, לבוב אין אינטרס לשדר את הטרנזקציה הישנה TX B2 (הטרנזקציות החדשות נותנות לו יותר). מהצד השני, אם אליס מנסה לרמות ע"י שידור TX A2, היא תצטרך לחכות שבועיים לפני שהיא תוכל להשתמש בכסף, אבל בוב, שכבר קיבל ממנה את המפתח הפרטי Batman (כשהם עדכנו את המאזן בינם), וכבר היה לו מראש את המפתח הפרטי Robin שהוא עצמו יצר, יוכל לקחת מיד את הכסף בלי לחכות שבועיים. זה האינטרס של אליס לא לשדר טרנזקציה ישנה, ובוב חייב לבדוק את הטרנזקציות בבלוקצ'יין כדי לבדוק אם אליס מנסה לרמות או לא. הבעיה נפתרה: כל עוד כולם פועלים מתוך האינטרס האישי שלהם, אף אחד לא ינסה לרמות. המנגנון הכלכלי מבוסס-התמריצים המתוחכם הזה נקרא RSMC: Revocable Sequence Maturity Contract, והוא ההשראה לפיתוח של רשת הברק.

כמו שהשם מרמז, החוזה (Contract) הוא ניתן-לביטול (Revocable) מכיוון שטרנזקציות שכבה שנייה ניתן להחליף בטרנזקציות חדשות יותר. הוא משתמש בנעילת-זמן על בסיס OP_CHECKSEQUENCEVERIFY, כלומר יש פה מספר-מעקב (Sequence), שמייצג את הזמן בבלוקצ'יין (כמו גובה בלוק או timestamp). מכיוון שהכסף נעול בזמן, הכסף צריך להגיע ל"בשלות" (Maturity) כדי שניתן יהיה להוציא אותו כשמספיק זמן עבר. ביחד, השיטה הזו קיבלה את השם: חוזה מבשיל ניתן-לביטול עם מספר-מעקב (Revocable Sequence Maturity Contract).

ל-RSMC יש את המגבלות שלו, מכיוון שהוא יכול לשרת רק שני משתתפים בכל פעם. אנחנו רוצים להרחיב את הרשת כדי שאנשים יוכלו לבצע תשלומים בצורה חלקה. עם שכלול קטן ל-RSMC, נגיע לבסיס של רשת הברק, שנקרא HTLC: Hashed Time Lock Contract – חוזה נעילת-זמן מגובב.

סיכום סדר הפעולות בשיטת RSMC (מומלץ להיעזר באיורים כשעוברים על הסעיפים):

  1. אליס מייצרת מפתח פרטי A1 ושולחת לבוב את המפתח הציבורי שלו.
  2. בוב מייצר מפתח פרטי B1 ושולח לאליס את המפתח הציבורי שלו.
  3. אליס מייצרת טרנזקציית תקצוב עם Output מסוים שיש בו 0.5 ביטקוין, וכדי להוציא אותם צריך גם חתימה מתאימה ל-A1 וגם חתימה מתאימה ל-B1. אליס עדיין לא משדרת את הטרנזקציה, אלא שולחת לבוב רק את ה-ID של הטרנזקציה וה-Output Number הרלוונטי.
  4. בוב מייצר מפתח פרטי Morty ושולח לאליס את המפתח הציבורי שלו.
  5. אליס מייצרת מפתח פרטי Rick, ובונה את TX A1, שמבזבזת את טרנזקציית התקצוב (כל טרנזקציות ההתחייבות מעכשיו יבזבזו את ה-Output המסוים של טרנזקציית התקצוב). למרות שיש לאליס את A1, היא עדיין לא מצרפת את החתימה שלה. אליס שולחת את הטרנזקציה לבוב.
  6. בוב בודק את הפרטים של הטרנזקציה TX A1 ושולח לאליס את החתימה שלו לטרנזקציה (באמצעות B1).
  7. אליס משדרת את טרנזקציית התקצוב, כי היא יודעת שיש לה את TX A1 עם החתימה של בוב, ואם היא רוצה לסגור את הערוץ היא יכולה לצרף את החתימה שלה (באמצעות A1), לשדר את הטרנזקציה ולקבל את ה-0.5 ביטקוין בחזרה.
  8. לצורך הסימטריה, בוב רוצה שתהיה לו TX B1. הוא בונה את הטרנזקציה ושולח את הפרטים שלה לאליס.
  9. אליס מסתכלת על הפרטים של הטרנזקציה TX B1 ושולחת לבוב את החתימה שלה (באמצעות A1). אין לה שום בעיה לחתום עליה, כי הטרנזקציה הזו נותנת לה את כל ה-0.5 ביטקוין שבערוץ. גם בוב יכול עכשיו לסגור את הערוץ באופן חד צדדי, ע"י צירוף החתימה שלו ל-TX B1 באמצעות B1, ושידור הטרנזקציה (טכנית אין לו סיבה אף פעם לעשות את זה כי אליס תקבל את כל ה-0.5 ביטקוין).
  10. שני הצדדים מחכים שטרנזקציית התקצוב תעבור מספיק confirmations. בתום שלב זה, הערוץ פתוח וניתן להתחיל להשתמש בו לביצוע תשלומים, לפי הצעדים המפורטים להלן.
  11. אליס רוצה לשלם 0.1 ביטקוין לבוב דרך הערוץ.
  12. אליס מייצרת שני מפתחות פרטיים: Batman ו-Tom, ושולחת לבוב את המפתחות הציבוריים שלהם.
  13. בוב מייצר שני מפתחות פרטיים: Robin ו-Jerry, ושולח לאליס את המפתחות הציבוריים שלהם.
  14. אליס בונה את טרנזקציית ההתחייבות TX A2 ושולחת אותה לבוב, ללא חתימות.
  15. בוב בודק את הפרטים של הטרנזקציה TX A2, ושולח לאליס את החתימה שלו (באמצעות B1).
  16. בוב בונה את טרנזקציית ההתחייבות TX B2 ושולח אותה לאליס, ללא חתימות.
  17. אליס מסתכלת על הפרטים של הטרנזקציה TX B2, ושולחת לבוב את החתימה שלה (באמצעות A1).
  18. אליס רוצה להבטיח לבוב שהיא לא תנסה לחתום ולשדר את טרנזקציית ההתחייבות הישנה TX A1. היא שולחת לבוב את המפתח הפרטי Rick. אם אליס תנסה לרמות, בוב ישתמש ב-Rick שהיא נתנה לו וב-Morty שהוא עצמו יצר, כדי לקחת לעצמו מייד את כל הכסף בערוץ. אם בוב רוצה לסגור את הערוץ באופן חד צדדי, הוא יעשה את זה ע"י שידור TX B2, החתימה שאליס נתנה לו בסעיף 17, וחתימה שהוא יכול לייצר (באמצעות B1). לכן מבחינת בוב התשלום הסתיים.
  19. לאליס לא אכפת שבוב ישדר את TX B1 שנותנת לה את המקסימום בערוץ (0.5 ביטקוין) – יותר ממה שמגיע לה (0.4 ביטקוין אחרי התשלום). אם אליס רוצה לסגור את הערוץ באופן חד צדדי, היא תעשה את זה ע"י שידור TX A2, החתימה שבוב נתן לה בסעיף 15, וחתימה שהיא יכולה לייצר (באמצעות A1). לכן גם מבחינת אליס התשלום הסתיים.
  20. אם הם רוצים לבצע תשלום נוסף:
    1. כל אחד ייצר שני מפתחות פרטיים חדשים וישלח לשני את המפתחות הציבוריים שלהם.
    2. אליס תבנה את TX A3 ותשלח אותה לבוב ללא חתימות. בוב יבדוק את הטרנזקציה ויענה לה עם החתימה שלו (באמצעות B1).
    3. בוב יבנה את TX B3 וישלח אותה לאליס ללא חתימות. אליס תבדוק את הטרנזקציה ותענה לו עם החתימה שלה (באמצעות A1).
    4. אליס תשלח לבוב את המפתח הפרטי Batman. אם היא תנסה לרמות ולשדר את TX A2 עם חתימות, בוב יגיב עם Batman (שהיא נתנה לו) ועם Robin (שהוא עצמו יצר) וייקח את כל הכסף לעצמו מייד.
    5. בוב ישלח לאליס את המפתח הפרטי Jerry. אם בוב ינסה לרמות ולשדר את TX B2 עם חתימות, אליס תגיב עם Tom (שהיא עצמה יצרה) ועם Jerry (שבוב נתן לה) ותיקח את כל הכסף לעצמה מייד.

חוזה נעילת-זמן מגובב

דמיינו שיש לנו שלושה משתתפים ושני ערוצים. ערוץ אחד פתוח בין אליס ובוב, והערוץ השני פתוח בין בוב לצ'רלי. אם אליס רוצה לשלוח כסף לצ'רלי, יש לה שתי אפשרויות:

  1. אליס וצ'רלי יכולים לפתוח ערוץ בינם ולבצע את הטרנזקציה
  2. אליס וצ'רלי יכולים להשתמש בערוצים הקיימים

נראה שהגישה הראשונה תעבוד, אבל היא לא תפתור את הבעיה כשמספר המשתתפים גדל. החשבון הוא פשוט:

  1. עבור 3 משתתפים אנחנו צריכים 3 ערוצים
  2. עבור 4 משתתפים אנחנו צריכים 6 ערוצים
  3. עבור 10 משתתפים אנחנו צריכים 45 ערוצים
  4. עבור 1000 משתתפים אנחנו צריכים 499,500 ערוצים!

זה פשוט יותר מדי ערוצים! בהשוואה לאלטרנטיבה שבה אליס וצ'רלי מבקשים מבוב לעזור, הגישה הראשונה היא פחות מועדפת ופחות ניתנת ליישום. הם כבר בנו ערוץ עם בוב, למה לא "לנתב" כסף דרך בוב הלוך וחזור?

פונקציית גיבוב (Hash) קריפטוגרפית

הערת מתרגם: מי שמכיר יכול לדלג על פרק זה.

כדי לממש ניתוב בין ערוצים, אנחנו צריכים לקחת בהשאלה כלי קריפטוגרפי שנקרא פונקציית גיבוב, ולהבין את המאפיינים שלה.

פונקציית גיבוב ממפה כל קלט לפלט בגודל קבוע. לדוגמא, פונקציית גיבוב פשוטה יכולה להיות לקחת מילים ולקבץ אותן לפי האות הראשונה.

הקלט הוא מילים (apple, agent), והפלטים הם אותיות (a). פונקציית גיבוב נוספת יכולה להיות פעולת ה-Modulo (מציאת שארית מחלוקה במספר). לדוגמא, אנחנו יכולים להגדיר פונקציית גיבוב שיכולה לקבל כ-input כל מספר שלם, ולחשב את השארית מחלוקה ב-7. לכל הפלטים יש גודל קבוע: מספר בעל ספרה אחת בין 0 ל-6.

פונקציית גיבוב קריפטוגרפית נדרשת לקיים את שתי התכונות הבאות:

  1. פונקציה חד-כיוונית (One-Way Function) – כלומר בהינתן פלט, קשה למצוא את הקלט. אם הפלט הוא אחד, קשה לדעת אם הקלט הוא 1, 8, או כל מספר שבחלוקה ב-7 נותן שארית 1.
  2. מניעת התנגשות (Collision Resistance) – כלומר זה קשה למצוא שני קלטים שנותנים את אותו פלט. לפונקציית הגיבוב הנ"ל דווקא אין את התכונה הזו, וקל למצוא למשל את הקלטים 2 ו-9 שנותנים את אותו פלט 2, או את שתי המילים apple, agent שהפלט עבורן הוא האות a.

פונקציות גיבוב קריפטוגרפיות משיגות את התכונות הללו באמצעות שימוש בפונקציות מתמטיות מורכבות. מבלי לצלול לתוך "מחילת הארנב", האינסטינקט מאחורי התכנון שלהן הוא קל להבנה. כדי לבנות פונקציה חד-כיוונית, נדרשת פונקציה מתמטית שקל לוודא אותה כשיודעים את התשובה, אבל קשה לפתור אותה. או ליתר דיוק, יותר קשה למצוא תשובה מאשר לבדוק תשובה. בקריפטוגרפיה, "להיות קשה" משמעותו לדרוש יותר כוח חישוב וזמן. פירוק לגורמים זו דוגמה טובה:

  1. אתגר ראשון: למצוא שני מספרים שהמכפלה שלהם היא 2449.
  2. אתגר שני: לבדוק ש-31 כפול 79 נותן 2449.

לא קשה להסיק שיותר קל לפתור את האתגר השני מאשר את הראשון. למרות שקריפטוגרפיה מתבססת על מודלים מתמטיים מורכבים (לדוגמא discrete logarithm), העיקרון הזה נשאר ללא שינוי. מצד שני, כדי להשיג מניעת התנגשות, הגודל של פלטים ייחודיים חייב לגדול משמעותית, כדי להקטין את הסיכוי שקלטים שונים יתנגשו ויתנו את אותה תוצאה. אחד האלגוריתמים הנפוצים ביותר, SHA256, נותן 2 בחזקת 256 פלטים אפשריים, שזה מספר אסטרונומי מעבר לכל דמיון.

דוגמה לשימוש בפונקציות גיבוב קריפטוגרפיות היא להסתיר סוד ואח"כ לחשוף אותו (הוכחה באפס ידיעה). דוגמא ביזארית יכולה להיות שאליס טוענת שהיא האדם הראשון בעולם שיודע ידיעה קסומה שיכולה להפוך אנשים למיליארדרים, אבל צ'רלי לא מאמין לה. אם אליס תספר לצ'רלי את הידיעה ישירות, בוב יקפוץ מיד ויטען שהוא ידע את הידיעה הזו קודם. כדי למנוע את גניבת זכויות היוצרים, אליס תפעיל פונקציית גיבוב קריפטוגרפית על הידיעה, תשתף את התוצאה עם כולם, ותטען שהיא יודעת את הידיעה הסודית מבלי לחשוף אותה.

היא תשתמש ב-SHA256 כדי לגבב את הפטנט הסודי, שמייצר את הפלט:

8816cee3feb85ccaad0557ffb2f6b38947a27bea4ccdea1835fded53ad71c31a

אליס אז תשתף את התוצאה עם צ'רלי. צ'רלי יכול עכשיו לבקש מבוב להראות לו את ההודעה המקורית שמתאימה לפלט הזה. כמובן שבוב לא יודע את התשובה, ולא יכול לזייף אותה. כעת זה בטוח לאליס לחשוף את הידיעה הסודית:

money is a social construct

תוכנית נאיבית – הסתרה וחשיפה של סוד

זו תהיה נאיביות פשוט לבקש מבוב להעביר את הכסף אם אליס רוצה לשלוח 1 ביטקוין לצ'רלי. לבוב יהיו את כל הסיבות לקחת את הכסף לעצמו בלי להעביר כלום לצ'רלי. כדי לפתור את הבעיה, פונקציית גיבוב קריפטוגרפית נכנסת לתכנית. אם אליס רוצה לשלוח 1 ביטקוין לצ'רלי, זהו צ'רלי שצריך להתחיל ב-"בקשת תשלום". הינה מה שנעשה:

  1. צ'רלי ייצר מספר רנדומלי r וישמור אותו לעצמו כסוד (נקרא גם Preimage).
  2. צ'רלי יפעיל פונקציית גיבוב על הסוד r, וישלח את התוצאה R לבוב יחד עם בקשת התשלום "דרוש מאליס תשלום של 1 ביטקוין".
  3. צ'רלי יחכה שבוב ישלם לו ביטקוין אחד. צ'רלי לא יסכים לספר לאף אחד את r עד שיקבל תשלום.

ברגע שבוב מקבל את בקשת התשלום ביחד עם הערך המגובב R, הוא יעביר אותם לאליס ויבקש ממנה שתשלם לו 1 ביטקוין, ע"י יצירת טרנזקציה עם סקריפט הנעילה הבא:

  1. אם עברו שלושה ימים, ונמצאת חתימה מאליס, אז אליס מקבלת את הכסף חזרה.
  2. אחרת, אם נמצאים גם חתימה של בוב וגם הערך שהגיבוב שלו נותן R (שהוא הסוד r), אז בוב מקבל את הכסף.

הערת מתרגם: ה-Else כאן הוא לא במובן של שפת-תכנות, כלומר הוא לא מבצע בדיקה ש-"חלפו פחות משלושה ימים". למעשה אין אופרטור בסקריפט של ביטקוין שבודק דבר כזה (הסבר בהמשך). המשמעות של ה-Else כאן היא "עוד דרך לבזבז את ה-Output, בין אם חלפו או לא חלפו שלושה ימים".

אם בוב יכול לקבל את r מצ'רלי אז הוא יוכל לשחרר את הנעילה ולבזבז את ה-UTXO. אחרת, כעבור שלושה ימים, אליס תוכל לקבל חזרה את הביטקוין שלה. דרישת שלושת הימים היא דרישה בזמן אבסולוטי, בניגוד לדרישת נעילת הזמן הקודמת שעסקנו בה. היא מאפשרת לאליס לקבל את הכסף חזרה אם בוב לא יכול לספק את הסוד בתוך שלושה ימים מרגע יצירת הטרנזקציה (בלי קשר מתי היא תשודר). כעת, כשבוב בטוח שהוא יקבל 1 ביטקוין מאליס אם הוא ידע בעתיד את הערך של r, הוא יכול לשלוח לצ'רלי 1 ביטקוין ע"י יצירת טרנזקציה דומה עם סקריפט הנעילה הבא:

  1. אם חלפו יומיים, ונמצאת חתימה של בוב, אז בוב יכול לקבל את הכסף חזרה.
  2. אחרת, אם נמצאים גם חתימה של צ'רלי וגם הערך שהגיבוב שלו נותן R, אז צ'רלי מקבל את הכסף.

הערת מתרגם: ההערה על ה-Else תקפה גם כאן כמו בשרטוט הקודם.

כדי לקבל את הכסף, צ'רלי חייב לחשוף את הסוד r לבוב אחרי שידור הטרנזקציה הזו, בטרנזקציה נוספת שמבזבזת את ה-Output. אם הטרנזקציה תשודר אבל צ׳רלי לא יבזבז את ה-Output, כעבור יומיים (זמן אבסולוטי) זו הופכת לטרנזקציה מסוכנת מאוד, כי שני הצדדים יכולים להתחרות על הכסף. מאידך אם צ׳רלי לא ישדר את הטרנזקציה בכלל, אחרי יומיים הערוץ לא יהיה שימושי יותר – בוב לא יסכים יותר להגדלת הצד שלו במאזן בערוץ זה (לא יסכים להחלפת טרנזקציות חדשות), כי הוא יודע שצ'רלי תמיד יכול לחכות שלא יהיה פעיל ואז לנסות את מזלו לשדר את הטרנזקציה הישנה ומייד לבזבז את ה-Output. הטרנזקציה הזו טובה רק אם צ׳רלי משתמש בה תוך יומיים וגם חושף את הסוד כדי לבזבז את ה-Output – אחרי יומיים היא יוצרת אי ודאות לשני הצדדים.

ברגע שבוב יודע את r (בהסתכלות על הבלוקצ׳יין), הוא יכול להוציא את הכסף מהטרנזקציה בינו לבין אליס. כדי שלכל משתתף יהיה מספיק זמן לפעול, משך הזמן הנעול הולך וקטן ככל שמתקרבים יותר ליעד הסופי של התשלום, כלומר צ'רלי מקבל יומיים לחשוף את r, אבל בוב מקבל שלושה ימים. הפעולה של חשיפת הסוד r לאליס מבוב מוכיחה שהוא כבר שלח את הביטקוין לצ'רלי, מכיוון שזו הדרך היחידה שבה בוב יכול לגלות את הערך הסודי.

אבל האם מישהו יכול לרמות?

הכסף של אליס מוגבל לחלוטין בתקופת שלושת הימים. ברגע שעברו שלושה ימים, אליס חופשית לבזבז את הכסף לא משנה אם לבוב יש את הסוד או לא. לגבי בוב, הוא יכול להוציא את הכסף רק אם הוא יודע את r. אפילו אם עברו שלושה ימים, בוב לא יכול להוציא את הכסף מבלי לדעת את r. בלי קשר לעדכון המאזנים, נראה שהתכנית הנוכחית היא סבירה אם:

  1. בוב מתכוון להשתמש ב-UTXO שלו ברגע שהוא יודע את r, כלומר הוא ישדר את הטרנזקציה שלו לפני שמסתיימים שלושת הימים.
  2. אליס מתכוונת להשתמש ב-UTXO שלה ברגע שעברו שלושה ימים, כלומר היא תשדר את הטרנזקציה שלה מייד כשחולפים שלושת הימים (אלא אם בוב השתמש ב-UTXO לפניה).

אם הם לא משדרים את הטרנזקציה בזמן הקצוב, הצד השני יכול לרמות ולקחת את הכסף. אבל אם טרנזקציית שכבה-שנייה משודרת, היא הופכת לטרנזקציה בין-שכבות, מה שסותר את הדרישה שלנו מרשת הברק – להשאיר את הטרנזקציות בתוך רשת הברק ככל שניתן. לפיכך, נדרשת תוכנית חדשה עם תכונות דומות ל-RSMC – אנחנו לא רוצים להתבסס על ההוגנות של המשתתפים, אלא להעניש את מי שמתנהג באופן לא הוגן.

עם הרקע הזה, הגיע הזמן ללמוד על התוכנית בשלמותה בחלק ב' – המימוש בפועל של רשת הברק.

הערות ומקורות ידע לפרק א'

  1. The Bitcoin Lightning Network: Scalable Off-Chain Instant Payments, Joseph Poon, Thaddeus Dryja
  2. Reaching the ground with lightning, Rusty Russell
  3. Cryptographic Hash Function
  4. A Fast and Scalable Payment Network with Bitcoin Duplex Micropayment Channels, Christian Decker, Roger Wattenhofer
  5. The Lightning Network Specifications has all the implementation details. The actual locking scripts used are specified in BOLT #3: Bitcoin Transaction and Script Formats
  6. I’ve set up a testing environment using bitcoind and lnd to help me understand the whole process. Here’s the gist of the trimmed log generated from lnd, which recorded how Alice and Bob opened a channel.
  7. A curated list of awesome Lightning Network projects for developers and crypto enthusiasts.