ipns實現機制解讀

ipns是ipfs的域名系統。

前言

將ipns記錄保存在dht之前,需要驗證發佈對象的真實性(有可能該對象是被別的節點冒用的),具體是通過檢測簽名是否與公鑰和節點ID匹配,因此需要知道公鑰。

ipfs init的時候,會自動生成RSA公私鑰,通過對RSA公鑰做multihash得到peerID,即peerID = multihash(pk)。

從v0.4.16開始,ipfs支持更新的ed25519算法生成公私鑰,公鑰可以嵌入到peerID中,因此不需要額外發送公鑰。

從v0.4.16開始,/ipns完全足夠work了。現在還保留/pk,主要是v0.4.16版本做了一次“軟分叉”,使得v0.4.16以後的版本能把IpnsEntry存到v0.4.16以前的版本,但是以前的版本不能把IpnsEntry存到之後的版本,這對以前的版本不公平,卻可以促進它們升級到更高版本,對整個網絡是有利的。

ipfs通過dht.PutValue函數將ipns記錄保存在本地以及其它peers的dht.datastore中;通過dht.GetValue函數從本地以及其它peers獲取記錄。

運行環境

版本: [email protected] [email protected]

本文運行兩個節點,一個在ubuntu,另外一個在windows,下文用ipfs1代表ubuntu端的ipfs,用ipfs2代表windows端的ipfs。兩個節點將彼此的地址添加到彼此的bootstrap中,形成由2個節點組成的測試網。

兩者的peerID分別爲:

ipfs1: QmdvR13vcQvRUy8vrdK7g2guwLVB4fQZGSbNifERCz5iNT
ipfs2: Qmco9fPhEC9aYsFxY3ZekoUMZucmNa9soWDXh6xgr6FsJy

將bitswap/dht/eventlog的log等級設置爲debug

$ ipfs log level bitswap debug & ipfs log level dht debug & ipfs log level eventlog debug & ipfs log level namesys debug & ipfs log level ipns-repub debug & ipfs log reprovider debug
[1] 4617
[2] 4618
Changed log level of 'dht' to 'debug'
Changed log level of 'bitswap' to 'debug'
Changed log level of 'eventlog' to 'debug'
[1]-  已完成               ipfs log level bitswap debug
[2]+  已完成               ipfs log level dht debug

普通操作

更新併發布ipns:

ipfs name publish

$ ipfs name publish QmStPNdn4LngCMAbw1nRS5YTsYDHr4HCbdy12y8uhsxS8o
Published to QmdvR13vcQvRUy8vrdK7g2guwLVB4fQZGSbNifERCz5iNT: /ipfs/QmStPNdn4LngCMAbw1nRS5YTsYDHr4HCbdy12y8uhsxS8o

log

18:43:37.010 DEBUG        dht: PutValue /pk/ 煍Hm+
3�#T˞�p�V
          {�w|!��m�5�0 routing.go:47
18:43:37.010 DEBUG        dht: getLocal /pk/ 煍Hm+
3�#T˞�p�V
          {�w|!��m�5�0 dht.go:245
18:43:37.010 DEBUG        dht: PutValue /ipns/ 煍Hm+
3�#T˞�p�V
          {�w|!��m�5�0 routing.go:47
18:43:37.010 DEBUG        dht: putLocal: /pk/ 煍Hm+
3�#T˞�p�V
          {�w|!��m�5�0 key:"/pk/\022 \347\205\215Hm+\n3\221\033#T\313\236\330p\372V\013{\276w|!\035\242\262m\2035\3010" value:"\010\000\022\246\0020\202\001\"0\r\006\t*\206H\206\367\r\001\001\001\005\000\003\202\001\017\0000\202\001\n\002\202\001\001\000\301\025\221\271Y\257D\254\373\372\200\rc\215\n\327\240>\255s*U\255\312\203\t\n_\244m\335\035\241\375\033\345$\236\024o).K\032\332&c\023uk\311\222\333\226\005\224O\206L\224\371\316\270\245\0062\023\255\252\236\224\372\320-\033\216\317~\221\325\216\304\236\246v\223*?\177\255\240\326\031\n\340?\277\231\036\010C\033jz!S\376r\313\226\331\346\375*\237\234\242\236\014\r\247\214\022-/\267\236\230\304\361L\244\244`b\322\305\005H\031\262H\221S\207!\271\263y/+\275@\267\002j\270l6`\273\331\331\355n\013\257-\334+\000p[\243B\300\376\354\035\234[\323B\035\217\340\254\326\330-&9y\311\307\032\325\263\201\001\355\334\334\270\0073\204*\2342;b\304@]%TP@t\312p\222\224:f\324u\025\234*S/\323ji\025\333\303T\353\314\201\217\tU\370'\007\355\002\351\350\r\301\013\002\003\001\000\001" timeReceived:"2020-02-19T02:43:37.010515835Z"  dht.go:263
18:43:37.010 DEBUG        dht: getLocal /ipns/ 煍Hm+
3�#T˞�p�V
          {�w|!��m�5�0 dht.go:245
18:43:37.011 DEBUG        dht: dialling Qmco9fPhEC9aYsFxY3ZekoUMZucmNa9soWDXh6xgr6FsJy took 0ms (as observed by the dht subsystem). dial_queue.go:331
18:43:37.011 DEBUG        dht: delivering dialled peer to DHT; took 0ms. dial_queue.go:186
18:43:37.011 DEBUG        dht: putLocal: /ipns/ 煍Hm+
3�#T˞�p�V
          {�w|!��m�5�0 key:"/ipns/\022 \347\205\215Hm+\n3\221\033#T\313\236\330p\372V\013{\276w|!\035\242\262m\2035\3010" value:"\n4/ipfs/QmStPNdn4LngCMAbw1nRS5YTsYDHr4HCbdy12y8uhsxS8o\022\200\002\021]\352\300:\3652.\252\336?\271\\\276\223&\255otsZ\231\372W~\177Z\377%V(\035\244\310\003y\311\003D\265\326\361U$&\007\223\230Z#Z\304\273\035<\006-\334\210\\\021\352\251$\r\217)#*\346\313\236\346\323\303\"R\335\372\377\336\"\347\323\341vY \244\177\327\334\335\351\341\3216\324\337\2423\324%\255\220\244*<\205\365\273\242\224\267\010#\202o\0323\325\273z&\023\255\246\033\303_\322\232\321G\262\000\273%\027Q\022\252\314B\204\266\014U\251\257E\233\375U\035e@95\230<\347T\360\201;\004\217\372\211\215\202\377\2373\036\210,\304_M\220Xm\301p\034$`iG\274q\004\271.%\235\226CR\206\020\310H\365\260\263\335\343\001\236\263e2\004V\265\266\355w7.C\303\2055\023\014=?\273u]\3101\010i\335f\343![0\216\013P\222g\245\327\031\251M\"M\030\000\"\0362020-02-20T02:43:37.005860075Z(\t:\253\002\010\000\022\246\0020\202\001\"0\r\006\t*\206H\206\367\r\001\001\001\005\000\003\202\001\017\0000\202\001\n\002\202\001\001\000\301\025\221\271Y\257D\254\373\372\200\rc\215\n\327\240>\255s*U\255\312\203\t\n_\244m\335\035\241\375\033\345$\236\024o).K\032\332&c\023uk\311\222\333\226\005\224O\206L\224\371\316\270\245\0062\023\255\252\236\224\372\320-\033\216\317~\221\325\216\304\236\246v\223*?\177\255\240\326\031\n\340?\277\231\036\010C\033jz!S\376r\313\226\331\346\375*\237\234\242\236\014\r\247\214\022-/\267\236\230\304\361L\244\244`b\322\305\005H\031\262H\221S\207!\271\263y/+\275@\267\002j\270l6`\273\331\331\355n\013\257-\334+\000p[\243B\300\376\354\035\234[\323B\035\217\340\254\326\330-&9y\311\307\032\325\263\201\001\355\334\334\270\0073\204*\2342;b\304@]%TP@t\312p\222\224:f\324u\025\234*S/\323ji\025\333\303T\353\314\201\217\tU\370'\007\355\002\351\350\r\301\013\002\003\001\000\001" timeReceived:"2020-02-19T02:43:37.01125562Z"  dht.go:263
18:43:37.011 DEBUG        dht: dialling Qmco9fPhEC9aYsFxY3ZekoUMZucmNa9soWDXh6xgr6FsJy took 0ms (as observed by the dht subsystem). dial_queue.go:331
18:43:37.012 DEBUG        dht: delivering dialled peer to DHT; took 0ms. dial_queue.go:186
18:43:37.012 DEBUG        dht: QUERY worker for: Qmco9fPhEC9aYsFxY3ZekoUMZucmNa9soWDXh6xgr6FsJy - not found, and no closer peers. query.go:312
18:43:37.012 DEBUG        dht: closestPeers query run error: routing: not found lookup.go:98
18:43:37.013 DEBUG        dht: QUERY worker for: Qmco9fPhEC9aYsFxY3ZekoUMZucmNa9soWDXh6xgr6FsJy - not found, and no closer peers. query.go:312
18:43:37.013 DEBUG        dht: closestPeers query run error: routing: not found lookup.go:98

從log可知,ipfs1前後putValue了2個ipns記錄,一個是/ipns,另外一個是/pk。

ipfs1通過調用PutValue函數,PutValue函數會首先檢查傳入的IpfsEntry(ipns記錄)的簽名和有效期,接着決定是否更新當前的IpfsEntry,更新的標準是: 先看Sequence,再看Validity,最後看Value。

相比舊的IpfsEntry,傳入的Sequence比較大則更新;比較小則返回錯誤;相等看Validity,傳入的Validity比較大更新,比較小返回錯誤,相等的話,再對比Value,如果Value還是一樣,代表兩個IpfsEntry一樣,更新記錄。換言之,該機制主要用於防止舊的記錄覆蓋新的記錄。

如果全部檢驗通過,ipfs1會首先把IpfsEntry記錄存到本地(dht.datastore),接着計算/ipns/xxx這個key的sha256,然後和ipfs1 peerID計算距離,從ipfs1的routingTable選出alpha個距離最近的節點,向它們發送put_value消息,內容是最新的IpfsEntry;

ipfs2收到ipfs1的put_value消息後,首先也會檢查傳入的IpfsEntry(ipns記錄)的簽名和有效期,接着決定是否更新當前的IpfsEntry,更新標準同上。

以下是IpnsEntry的結構:

type IpnsEntry struct {
	Value        []byte                  `protobuf:"bytes,1,req,name=value" json:"value,omitempty"`
	Signature    []byte                  `protobuf:"bytes,2,req,name=signature" json:"signature,omitempty"`
	ValidityType *IpnsEntry_ValidityType `protobuf:"varint,3,opt,name=validityType,enum=ipns.pb.IpnsEntry_ValidityType" json:"validityType,omitempty"`
	Validity     []byte                  `protobuf:"bytes,4,opt,name=validity" json:"validity,omitempty"`
	Sequence     *uint64                 `protobuf:"varint,5,opt,name=sequence" json:"sequence,omitempty"`
	Ttl          *uint64                 `protobuf:"varint,6,opt,name=ttl" json:"ttl,omitempty"`
	// in order for nodes to properly validate a record upon receipt, they need the public
	// key associated with it. For old RSA keys, its easiest if we just send this as part of
	// the record itself. For newer ed25519 keys, the public key can be embedded in the
	// peerID, making this field unnecessary.
	PubKey               []byte   `protobuf:"bytes,7,opt,name=pubKey" json:"pubKey,omitempty"`

其中,value就是剛剛name publish後的值,在本文是QmStPNdn4LngCMAbw1nRS5YTsYDHr4HCbdy12y8uhsxS8o。

Validity是有效期,默認是24h,超過該有效期,這個記錄就是無效的。

Sequence用於標識版本,Sequence越大表示越新,只有value變動了,Sequence才加1。存儲前先判斷自己是否有這個記錄,如果沒有,驗證簽名和有效期通過後保存;如果有,取出記錄,對比Sequence,如果新記錄的Sequence更大,則保存新記錄。

Ttl(Time to live),作用等同於ping中TTL。

默認republish時間

ipfs config文件

"Ipns": {
    "RecordLifetime": "",
    "RepublishPeriod": "",
    "ResolveCacheSize": 128
  }

默認republish時間爲4h,默認記錄有效期爲24h

// DefaultRebroadcastInterval is the default interval at which we rebroadcast IPNS records
var DefaultRebroadcastInterval = time.Hour * 4

// InitialRebroadcastDelay is the delay before first broadcasting IPNS records on start
var InitialRebroadcastDelay = time.Minute * 1

// FailureRetryInterval is the interval at which we retry IPNS records broadcasts (when they fail)
var FailureRetryInterval = time.Minute * 5

// DefaultRecordLifetime is the default lifetime for IPNS records
const DefaultRecordLifetime = time.Hour * 24

ipfs name resolve

ipfs1 name resolve

$ ipfs name resolve /ipns/QmdvR13vcQvRUy8vrdK7g2guwLVB4fQZGSbNifERCz5iNT
/ipfs/QmStPNdn4LngCMAbw1nRS5YTsYDHr4HCbdy12y8uhsxS8o

ipfs1 log

01:37:11.910 DEBUG    namesys: RoutingResolver resolving QmdvR13vcQvRUy8vrdK7g2guwLVB4fQZGSbNifERCz5iNT routing.go:53
01:37:11.910 DEBUG        dht: getPublicKey for: QmdvR13vcQvRUy8vrdK7g2guwLVB4fQZGSbNifERCz5iNT records.go:27
01:37:11.910 DEBUG        dht: getLocal /ipns/ 煍Hm+
3�#T˞�p�V
          {�w|!��m�5�0 dht.go:245
01:37:11.911 DEBUG        dht: have it locally routing.go:290
01:37:11.911 DEBUG        dht: peers in rt: 1 [Qmco9fPhEC9aYsFxY3ZekoUMZucmNa9soWDXh6xgr6FsJy] routing.go:307
01:37:11.911 DEBUG        dht: dialling Qmco9fPhEC9aYsFxY3ZekoUMZucmNa9soWDXh6xgr6FsJy took 0ms (as observed by the dht subsystem). dial_queue.go:331
01:37:11.911 DEBUG    namesys: resolved /ipns/QmdvR13vcQvRUy8vrdK7g2guwLVB4fQZGSbNifERCz5iNT to /ipfs/QmStPNdn4LngCMAbw1nRS5YTsYDHr4HCbdy12y8uhsxS8o base.go:69
01:37:11.913 DEBUG        dht: getValueOrPeers: got value dht.go:197
01:37:11.913 DEBUG        dht: QUERY worker for: Qmco9fPhEC9aYsFxY3ZekoUMZucmNa9soWDXh6xgr6FsJy - not found, and no closer peers. query.go:312

ipfs2 log

17:42:14.044 DEBUG        dht: Qmco9fPhEC9aYsFxY3ZekoUMZucmNa9soWDXh6xgr6FsJy handleGetValue for key: /ipns/ 煍Hm+
3�#T˞�p�V{�w|!��m�5�0 handlers.go:51
17:42:14.044 DEBUG        dht: Qmco9fPhEC9aYsFxY3ZekoUMZucmNa9soWDXh6xgr6FsJy handleGetValue looking into ds handlers.go:90
17:42:14.044 DEBUG        dht: Qmco9fPhEC9aYsFxY3ZekoUMZucmNa9soWDXh6xgr6FsJy handleGetValue looking into ds GOT [10 40 47 105 112 110 115 47 18 32 231 133 141 72 109 43 10 51 145 27 35 84 203 158 216 112 250 86 11 123 190 119 124 33 29 162 178 109 131 53 193 48 18 139 5 10 52 47 105 112 102 115 47 81 109 83 116 80 78 100 110 52 76 110 103 67 77 65 98 119 49 110 82 83 53 89 84 115 89 68 72 114 52 72 67 98 100 121 49 50 121 56 117 104 115 120 83 56 111 18 128 2 144 152 67 228 238 174 28 125 246 248 183 187 74 71 183 93 243 152 131 185 173 94 173 151 83 82 151 107 222 112 3 213 29 87 18 251 76 147 149 69 224 90 101 163 0 69 224 136 204 233 13 75 130 115 245 12 157 96 71 209 146 192 72 69 52 142 184 92 36 254 211 134 178 24 96 25 117 64 84 195 214 196 47 6 211 59 174 174 69 112 240 89 133 73 215 45 54 145 95 229 138 108 118 106 223 43 224 74 237 207 11 171 80 26 33 165 18 16 97 109 9 151 3 13 13 112 94 143 216 45 253 47 61 254 188 168 21 250 99 120 219 184 135 55 150 242 81 222 141 110 197 192 149 224 122 182 132 139 246 128 84 237 208 169 200 131 195 175 234 242 76 21 175 115 21 101 187 216 145 72 74 57 71 30 11 175 31 131 232 165 116 229 219 227 116 29 249 202 143 24 163 159 125 92 80 68 39 6 8 234 250 73 22 1 58 249 16 48 9 31 118 45 29 184 76 33 241 78 126 205 251 35 154 132 192 20 190 15 35 240 254 109 152 144 231 28 247 107 47 241 198 120 222 135 13 243 24 0 34 30 50 48 50 48 45 48 50 45 50 48 84 48 56 58 49 53 58 49 48 46 53 56 57 54 56 54 54 53 57 90 40 9 58 171 2 8 0 18 166 2 48 130 1 34 48 13 6 9 42 134 72 134 247 13 1 1 1 5 0 3 130 1 15 0 48 130 1 10 2 130 1 1 0 193 21 145 185 89 175 68 172 251 250 128 13 99 141 10 215 160 62 173 115 42 85 173 202 131 9 10 95 164 109 221 29 161 253 27 229 36 158 20 111 41 46 75 26 218 38 99 19 117 107 201 146 219 150 5 148 79 134 76 148 249 206 184 165 6 50 19 173 170 158 148 250 208 45 27 142 207 126 145 213 142 196 158 166 118 147 42 63 127 173 160 214 25 10 224 63 191 153 30 8 67 27 106 122 33 83 254 114 203 150 217 230 253 42 159 156 162 158 12 13 167 140 18 45 47 183 158 152 196 241 76 164 164 96 98 210 197 5 72 25 178 72 145 83 135 33 185 179 121 47 43 189 64 183 2 106 184 108 54 96 187 217 217 237 110 11 175 45 220 43 0 112 91 163 66 192 254 236 29 156 91 211 66 29 143 224 172 214 216 45 38 57 121 201 199 26 213 179 129 1 237 220 220 184 7 51 132 42 156 50 59 98 196 64 93 37 84 80 64 116 202 112 146 148 58 102 212 117 21 156 42 83 47 211 106 105 21 219 195 84 235 204 129 143 9 85 248 39 7 237 2 233 232 13 193 11 2 3 1 0 1 42 28 50 48 50 48 45 48 50 45 49 57 84 48 56 58 49 52 58 50 52 46 51 51 50 55 53 54 53 90] handlers.go:93
17:42:14.044 DEBUG        dht: Qmco9fPhEC9aYsFxY3ZekoUMZucmNa9soWDXh6xgr6FsJy handleGetValue success! handlers.go:105

name resolve /ipns/xxx的時候,ipfs1首先會解析peerID,看能否獲得peerID對應publicKey。接着調用SearchValue,SearchValue先從本地(dht.datastore)中查,由於不知道當前該記錄是否爲最新的記錄,不管本地有沒有這個記錄,ipfs2會先計算/ipns/xxx這個key的sha256,然後和ipfs1 peerID計算距離,從ipfs1的routingTable選出alpha個距離最近的節點,向他們發送get_value消息,詢問ipns/xxx這個key對應的value。

ipfs2收到get_value請求後,首先從本地(dht.datastore)中查找,由於不知道當前該記錄是否爲最新的記錄,不管本地有沒有這個記錄,ipfs2都會從routingTable選出K(現爲20)個距離記錄sha256("/ipns/xxx")最近的節點(closerPeers),將節點信息(closerPeers)和記錄(兩者都可爲空)發給ipfs1。

ipfs1收到ipfs2的回覆後,如果resp中有記錄就將其收集起來,如果resp中有closerPeers,則將它們添加到peerstore.AddrBook(值得注意的是,該AddrBook帶有超時機制),以便接下來向它們發起get_value查詢請求。

ipfs1最後把本地和從網絡詢問到的IpfsEntry收集起來,選出最新的IpfsEntry(新舊的判斷標準同上文),如果發現本地的記錄是舊的或者本地原本沒記錄,就更新本地記錄;如果發現其它節點發過來的IpfsEntry是舊的,就向它們發送put value消息,內容是最新的IpfsEntry,以更新它們的記錄。對於那些回覆中不帶有IpfsEntry的節點,原來就不存該記錄(IpfsEntry),所以不會給它們put value。

ipfs cat /ipns/xxx

ipfs2 cat /ipns/xxx

$ ipfs cat /ipns/QmdvR13vcQvRUy8vrdK7g2guwLVB4fQZGSbNifERCz5iNT
Hello, Now is midnight

ipfs1 log

08:02:58.587 DEBUG        dht: QmdvR13vcQvRUy8vrdK7g2guwLVB4fQZGSbNifERCz5iNT handleGetValue for key: /ipns/ 煍Hm+
3�#T˞�p�V
          {�w|!��m�5�0 handlers.go:51
08:02:58.587 DEBUG        dht: QmdvR13vcQvRUy8vrdK7g2guwLVB4fQZGSbNifERCz5iNT handleGetValue looking into ds handlers.go:90
08:02:58.587 DEBUG        dht: QmdvR13vcQvRUy8vrdK7g2guwLVB4fQZGSbNifERCz5iNT handleGetValue looking into ds GOT [10 40 47 105 112 110 115 47 18 32 231 133 141 72 109 43 10 51 145 27 35 84 203 158 216 112 250 86 11 123 190 119 124 33 29 162 178 109 131 53 193 48 18 139 5 10 52 47 105 112 102 115 47 81 109 83 116 80 78 100 110 52 76 110 103 67 77 65 98 119 49 110 82 83 53 89 84 115 89 68 72 114 52 72 67 98 100 121 49 50 121 56 117 104 115 120 83 56 111 18 128 2 111 51 121 114 140 69 130 232 189 19 234 222 79 13 25 90 20 239 252 200 98 249 140 229 109 91 146 195 5 207 29 1 190 62 167 12 248 144 8 224 191 74 0 137 73 165 165 193 203 250 120 219 30 193 173 87 66 30 221 233 203 79 184 227 82 21 184 160 241 152 25 129 137 17 162 182 3 191 180 163 14 50 30 227 242 187 234 36 49 253 56 67 152 83 190 166 253 115 20 118 135 213 155 154 150 126 100 195 250 197 97 82 34 212 164 62 144 244 111 51 23 255 71 93 185 15 89 67 154 64 145 68 33 147 126 194 62 46 180 212 193 109 4 142 229 20 72 103 98 211 130 17 237 25 183 194 160 27 27 0 80 196 203 5 202 36 8 215 7 244 178 199 124 249 73 33 231 125 63 139 52 187 155 81 192 142 173 12 1 62 132 95 135 168 83 219 75 13 13 232 138 90 135 142 92 201 88 100 97 200 135 219 215 47 76 133 221 220 104 212 159 115 39 153 226 152 15 176 157 250 160 188 42 225 67 21 180 40 44 74 205 51 162 85 200 38 249 214 153 7 180 250 208 104 161 151 24 0 34 30 50 48 50 48 45 48 50 45 49 55 84 49 54 58 48 48 58 48 50 46 48 48 55 50 57 54 48 53 53 90 40 2 58 171 2 8 0 18 166 2 48 130 1 34 48 13 6 9 42 134 72 134 247 13 1 1 1 5 0 3 130 1 15 0 48 130 1 10 2 130 1 1 0 193 21 145 185 89 175 68 172 251 250 128 13 99 141 10 215 160 62 173 115 42 85 173 202 131 9 10 95 164 109 221 29 161 253 27 229 36 158 20 111 41 46 75 26 218 38 99 19 117 107 201 146 219 150 5 148 79 134 76 148 249 206 184 165 6 50 19 173 170 158 148 250 208 45 27 142 207 126 145 213 142 196 158 166 118 147 42 63 127 173 160 214 25 10 224 63 191 153 30 8 67 27 106 122 33 83 254 114 203 150 217 230 253 42 159 156 162 158 12 13 167 140 18 45 47 183 158 152 196 241 76 164 164 96 98 210 197 5 72 25 178 72 145 83 135 33 185 179 121 47 43 189 64 183 2 106 184 108 54 96 187 217 217 237 110 11 175 45 220 43 0 112 91 163 66 192 254 236 29 156 91 211 66 29 143 224 172 214 216 45 38 57 121 201 199 26 213 179 129 1 237 220 220 184 7 51 132 42 156 50 59 98 196 64 93 37 84 80 64 116 202 112 146 148 58 102 212 117 21 156 42 83 47 211 106 105 21 219 195 84 235 204 129 143 9 85 248 39 7 237 2 233 232 13 193 11 2 3 1 0 1 42 30 50 48 50 48 45 48 50 45 49 54 84 49 54 58 48 48 58 48 50 46 48 49 48 56 55 54 49 56 51 90] handlers.go:93
08:02:58.587 DEBUG        dht: QmdvR13vcQvRUy8vrdK7g2guwLVB4fQZGSbNifERCz5iNT handleGetValue success! handlers.go:105
08:02:58.590  INFO    bitswap: Sending block [Block QmStPNdn4LngCMAbw1nRS5YTsYDHr4HCbdy12y8uhsxS8o] to Qmco9fPhEC9aYsFxY3ZekoUMZucmNa9soWDXh6xgr6FsJy workers.go:94
08:02:58.601 DEBUG        dht: QmdvR13vcQvRUy8vrdK7g2guwLVB4fQZGSbNifERCz5iNT adding Qmco9fPhEC9aYsFxY3ZekoUMZucmNa9soWDXh6xgr6FsJy as a provider for 'QmStPNdn4LngCMAbw1nRS5YTsYDHr4HCbdy12y8uhsxS8o'
 handlers.go:351
08:02:58.602 DEBUG        dht: received provider Qmco9fPhEC9aYsFxY3ZekoUMZucmNa9soWDXh6xgr6FsJy for QmStPNdn4LngCMAbw1nRS5YTsYDHr4HCbdy12y8uhsxS8o (addrs: [/ip4/192.168.1.3/tcp/4001 /ip4/169.254.72.9/tcp/4001 /ip4/192.168.56.1/tcp/4001 /ip4/192.168.25.1/tcp/4001 /ip4/192.168.5.1/tcp/4001 /ip4/127.0.0.1/tcp/4001 /ip6/2409:8a55:435:8000:48b9:2f2b:e352:4f47/tcp/4001 /ip6/2409:8a55:435:8000:b4b1:84fe:321b:8183/tcp/4001 /ip6/::1/tcp/4001]) handlers.go:368

ipfs2 log

00:02:17.476 DEBUG        dht: getPublicKey for: QmdvR13vcQvRUy8vrdK7g2guwLVB4fQZGSbNifERCz5iNT records.go:27
00:02:17.477 DEBUG        dht: getLocal /ipns/ 煍Hm+
3�#T˞�p�V{�w|!��m�5�0 dht.go:245
00:02:17.477 DEBUG        dht: have it locally routing.go:290
00:02:17.477 DEBUG        dht: peers in rt: 1 [QmdvR13vcQvRUy8vrdK7g2guwLVB4fQZGSbNifERCz5iNT] routing.go:307
00:02:17.477 DEBUG        dht: dialling QmdvR13vcQvRUy8vrdK7g2guwLVB4fQZGSbNifERCz5iNT took 0ms (as observed by the dht subsystem). dial_queue.go:331
00:02:17.477 DEBUG        dht: delivering dialled peer to DHT; took 0ms. dial_queue.go:186
00:02:17.479 DEBUG        dht: getValueOrPeers: got value dht.go:197
00:02:17.479 DEBUG        dht: QUERY worker for: QmdvR13vcQvRUy8vrdK7g2guwLVB4fQZGSbNifERCz5iNT - not found, and no closer peers. query.go:312
00:02:17.480  INFO    bitswap: want blocks: [QmStPNdn4LngCMAbw1nRS5YTsYDHr4HCbdy12y8uhsxS8o] wantmanager.go:73
00:02:17.482 DEBUG    bitswap: got block [Block QmStPNdn4LngCMAbw1nRS5YTsYDHr4HCbdy12y8uhsxS8o] from QmdvR13vcQvRUy8vrdK7g2guwLVB4fQZGSbNifERCz5iNT bitswap.go:337
00:02:17.486 DEBUG        dht: Provide  QmStPNdn4LngCMAbw1nRS5YTsYDHr4HCbdy12y8uhsxS8o routing.go:407

ipfs2通過dht調用GetValue函數,GetValue函數會調用SearchValue函數尋找記錄,SearchValue具體過程同上文"ipns resolve"中描述的過程一樣。

ipfs2拿到最新的記錄後,解析該記錄,得到一個block的CID,ipfs1在自己的datastore找這個block,如果找不到,則通過bitswap向ipfs1發送wantlist請求,在拿到塊後,向DHT網絡provide了這個塊,表明自己提供這個塊的下載。

指定操作

當前生成的key如下:

$ ipfs key list -l
QmdvR13vcQvRUy8vrdK7g2guwLVB4fQZGSbNifERCz5iNT self   

self就是節點ID,是默認的key。

ipfs name publish命令的完整形式如下:

ipfs name publish [--resolve=false] [--lifetime=<lifetime> | -t] [--allow-offline] [--ttl=<ttl>] [--key=<key> | -k] [--quieter | -Q] [--]
                    <ipfs-path>

key參數用於指定ipns使用哪個key,不指定的話默認使用self

使用ed25519生成公私鑰對

$ ipfs key gen -t ed25519 -s 2048 edKey
12D3KooWSWds5zGmaSVg7ig412MVmAEK98QN456ZFTKxU1NYiwUy

$ ipfs key list -l
QmdvR13vcQvRUy8vrdK7g2guwLVB4fQZGSbNifERCz5iNT       self   
12D3KooWSWds5zGmaSVg7ig412MVmAEK98QN456ZFTKxU1NYiwUy edKey   

ipfs name publish的時候使用新創建的edKey

$ ipfs name publish -k edKey QmStPNdn4LngCMAbw1nRS5YTsYDHr4HCbdy12y8uhsxS8o
Published to 12D3KooWSWds5zGmaSVg7ig412MVmAEK98QN456ZFTKxU1NYiwUy: /ipfs/QmStPNdn4LngCMAbw1nRS5YTsYDHr4HCbdy12y8uhsxS8o

log

19:15:46.042 DEBUG        dht: getLocal /ipns/ �
                                                  �_���"�:K43{��B�(���P���A<�D�� dht.go:245
19:15:46.042 DEBUG        dht: peers in rt: 1 [Qmco9fPhEC9aYsFxY3ZekoUMZucmNa9soWDXh6xgr6FsJy] routing.go:307
19:15:46.043 DEBUG        dht: dialling Qmco9fPhEC9aYsFxY3ZekoUMZucmNa9soWDXh6xgr6FsJy took 0ms (as observed by the dht subsystem). dial_queue.go:331
19:15:46.043 DEBUG        dht: delivering dialled peer to DHT; took 0ms. dial_queue.go:186
19:15:46.044 WARNI        dht: getValueOrPeers: routing.ErrNotFound dht.go:215
19:15:46.044 DEBUG        dht: ERROR worker for: Qmco9fPhEC9aYsFxY3ZekoUMZucmNa9soWDXh6xgr6FsJy routing: not found query.go:286
19:15:46.044 DEBUG        dht: loggableKey could not cast key to a CID: 2f69706e732f002408011220f80bf85f95f0fe22b23a4b34337bc18b42a928e6d6ff50e4f1ab413cb444d5e6 expected 1 as the cid version number, got: 0 lookup.go:44
19:15:46.044 DEBUG        dht: PutValue /ipns/ �
                                                  �_���"�:K43{��B�(���P���A<�D�� routing.go:47
19:15:46.044 DEBUG        dht: getLocal /ipns/ �
                                                  �_���"�:K43{��B�(���P���A<�D�� dht.go:245
19:15:46.045 DEBUG        dht: putLocal: /ipns/ �
                                                   �_���"�:K43{��B�(���P���A<�D�� key:"/ipns/\000$\010\001\022 \370\013\370_\225\360\376\"\262:K43{\301\213B\251(\346\326\377P\344\361\253A<\264D\325\346" value:"\n4/ipfs/QmStPNdn4LngCMAbw1nRS5YTsYDHr4HCbdy12y8uhsxS8o\022@N\025\263!s\325\224\303F,`\3201u&\253\255\237\036\300\003\366{\321\340;\225\353\221\373Zu\226\345O\223oC\375\r\244\343Q\206\030\031\006\307s\315N\356\257\276[\r\234_\031\217\204\373\006\010\030\000\"\0362020-02-20T03:15:46.042676531Z(\000" timeReceived:"2020-02-19T03:15:46.045003755Z"  dht.go:263
19:15:46.045 DEBUG        dht: loggableKey could not cast key to a CID: 2f69706e732f002408011220f80bf85f95f0fe22b23a4b34337bc18b42a928e6d6ff50e4f1ab413cb444d5e6 expected 1 as the cid version number, got: 0 lookup.go:44
19:15:46.045 DEBUG        dht: dialling Qmco9fPhEC9aYsFxY3ZekoUMZucmNa9soWDXh6xgr6FsJy took 0ms (as observed by the dht subsystem). dial_queue.go:331
19:15:46.045 DEBUG        dht: delivering dialled peer to DHT; took 0ms. dial_queue.go:186
19:15:46.045 DEBUG        dht: QUERY worker for: Qmco9fPhEC9aYsFxY3ZekoUMZucmNa9soWDXh6xgr6FsJy - not found, and no closer peers. query.go:312
19:15:46.045 DEBUG        dht: closestPeers query run error: routing: not found lookup.go:98
19:15:46.046 DEBUG        dht: loggableKey could not cast key to a CID: 2f69706e732f002408011220f80bf85f95f0fe22b23a4b34337bc18b42a928e6d6ff50e4f1ab413cb444d5e6 expected 1 as the cid version number, got: 0 lookup.go:44

由log可以看出,此處只有/ipns,不再有/pk,因爲用的是通過ed25519生成的key,可以通過peerID反推出pk,繼而檢驗/ipns記錄的真實性。

當ipfs name publish時,如果使用的是RSA生成的key,IpnsEntry(也就是ipns記錄)中的PubKey字段記錄了公鑰,存儲到DHT之前(即使是自己也)需要先使用該公鑰驗證entry中的簽名,驗證通過方可存儲,以保證存儲對象可信。

如果使用的是ed25519生成的key,IpnsEntry(也就是ipns記錄)中的PubKey字段是空的,因爲通過peerID就可以反推出公鑰。

v0.4.16之前的做法是:

IpnsEntry沒有PubKey這個字段,通過DHT中的putValue存2條記錄,一條是/ipns,key是/ipns/peerID,valueIpnsEntry/pkkey/pk/peerID, value是IpnsEntry;另外一條是/pk,key是/pk/peerID,value是PublicKey,即公鑰存在另外一條記錄,通過peerID即可獲得。可見,現在(V0.4.15以後)的做法更加合理。

從上面我們可以知道,這個版本(v0.4.23)的ipfs,/ipns完全能夠work了。現在還保留/pk,主要是v0.4.16版本做了一次“軟分叉”,使得v0.4.16以後的版本能把IpnsEntry存到v0.4.16以前的版本,但是以前的版本不能把IpnsEntry存到之後的版本,這對以前的版本不公平,卻可以促進它們升級到更高版本,對整個網絡是有利的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章