github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/storage/feed/request_test.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:44</date> 10 //</624450119374213120> 11 12 13 package feed 14 15 import ( 16 "bytes" 17 "encoding/binary" 18 "encoding/json" 19 "fmt" 20 "reflect" 21 "testing" 22 23 "github.com/ethereum/go-ethereum/crypto" 24 "github.com/ethereum/go-ethereum/swarm/storage" 25 "github.com/ethereum/go-ethereum/swarm/storage/feed/lookup" 26 ) 27 28 func areEqualJSON(s1, s2 string) (bool, error) { 29 //技巧的功劳:turtlemonvh https://gist.github.com/turtlemonvh/e4f7404e283887fadb8ad275a99596f67 30 var o1 interface{} 31 var o2 interface{} 32 33 err := json.Unmarshal([]byte(s1), &o1) 34 if err != nil { 35 return false, fmt.Errorf("Error mashalling string 1 :: %s", err.Error()) 36 } 37 err = json.Unmarshal([]byte(s2), &o2) 38 if err != nil { 39 return false, fmt.Errorf("Error mashalling string 2 :: %s", err.Error()) 40 } 41 42 return reflect.DeepEqual(o1, o2), nil 43 } 44 45 //TestEncodingDecodingUpdateRequests确保正确序列化请求 46 //同时还通过加密方式检查只有提要的所有者才能更新它。 47 func TestEncodingDecodingUpdateRequests(t *testing.T) { 48 49 charlie := newCharlieSigner() //查理 50 bob := newBobSigner() //鲍勃 51 52 //为我们的好人查理的名字创建一个提要 53 topic, _ := NewTopic("a good topic name", nil) 54 firstRequest := NewFirstRequest(topic) 55 firstRequest.User = charlie.Address() 56 57 //我们现在对创建消息进行编码,以模拟通过网络发送的消息。 58 messageRawData, err := firstRequest.MarshalJSON() 59 if err != nil { 60 t.Fatalf("Error encoding first feed update request: %s", err) 61 } 62 63 //…消息到达并被解码… 64 var recoveredFirstRequest Request 65 if err := recoveredFirstRequest.UnmarshalJSON(messageRawData); err != nil { 66 t.Fatalf("Error decoding first feed update request: %s", err) 67 } 68 69 //…但是验证应该失败,因为它没有签名! 70 if err := recoveredFirstRequest.Verify(); err == nil { 71 t.Fatal("Expected Verify to fail since the message is not signed") 72 } 73 74 //我们现在假设feed ypdate是被创建和传播的。 75 76 const expectedSignature = "0x7235b27a68372ddebcf78eba48543fa460864b0b0e99cb533fcd3664820e603312d29426dd00fb39628f5299480a69bf6e462838d78de49ce0704c754c9deb2601" 77 const expectedJSON = `{"feed":{"topic":"0x6120676f6f6420746f706963206e616d65000000000000000000000000000000","user":"0x876a8936a7cd0b79ef0735ad0896c1afe278781c"},"epoch":{"time":1000,"level":1},"protocolVersion":0,"data":"0x5468697320686f75722773207570646174653a20537761726d2039392e3020686173206265656e2072656c656173656421"}` 78 79 //将一个未签名的更新请求放在一起,我们将序列化该请求以将其发送给签名者。 80 data := []byte("This hour's update: Swarm 99.0 has been released!") 81 request := &Request{ 82 Update: Update{ 83 ID: ID{ 84 Epoch: lookup.Epoch{ 85 Time: 1000, 86 Level: 1, 87 }, 88 Feed: firstRequest.Update.Feed, 89 }, 90 data: data, 91 }, 92 } 93 94 messageRawData, err = request.MarshalJSON() 95 if err != nil { 96 t.Fatalf("Error encoding update request: %s", err) 97 } 98 99 equalJSON, err := areEqualJSON(string(messageRawData), expectedJSON) 100 if err != nil { 101 t.Fatalf("Error decoding update request JSON: %s", err) 102 } 103 if !equalJSON { 104 t.Fatalf("Received a different JSON message. Expected %s, got %s", expectedJSON, string(messageRawData)) 105 } 106 107 //现在,编码的消息messagerawdata通过网络发送并到达签名者。 108 109 //尝试从编码的消息中提取更新请求 110 var recoveredRequest Request 111 if err := recoveredRequest.UnmarshalJSON(messageRawData); err != nil { 112 t.Fatalf("Error decoding update request: %s", err) 113 } 114 115 //对请求进行签名,看看它是否与上面预先定义的签名匹配。 116 if err := recoveredRequest.Sign(charlie); err != nil { 117 t.Fatalf("Error signing request: %s", err) 118 } 119 120 compareByteSliceToExpectedHex(t, "signature", recoveredRequest.Signature[:], expectedSignature) 121 122 //弄乱签名看看会发生什么。为了改变签名,我们简单地将其解码为JSON 123 //更改签名字段。 124 var j updateRequestJSON 125 if err := json.Unmarshal([]byte(expectedJSON), &j); err != nil { 126 t.Fatal("Error unmarshalling test json, check expectedJSON constant") 127 } 128 j.Signature = "Certainly not a signature" 129 corruptMessage, _ := json.Marshal(j) //用错误的签名对邮件进行编码 130 var corruptRequest Request 131 if err = corruptRequest.UnmarshalJSON(corruptMessage); err == nil { 132 t.Fatal("Expected DecodeUpdateRequest to fail when trying to interpret a corrupt message with an invalid signature") 133 } 134 135 //现在假设Bob想要创建一个关于同一个feed的更新, 136 //用他的私人钥匙签名 137 if err := request.Sign(bob); err != nil { 138 t.Fatalf("Error signing: %s", err) 139 } 140 141 //现在,Bob对消息进行编码,以便通过网络发送… 142 messageRawData, err = request.MarshalJSON() 143 if err != nil { 144 t.Fatalf("Error encoding message:%s", err) 145 } 146 147 //…消息到达我们的群节点并被解码。 148 recoveredRequest = Request{} 149 if err := recoveredRequest.UnmarshalJSON(messageRawData); err != nil { 150 t.Fatalf("Error decoding message:%s", err) 151 } 152 153 //在检查鲍勃的最新消息之前,让我们先看看如果我们搞砸了会发生什么。 154 //在签名的时候看看verify是否捕捉到它 155 savedSignature := *recoveredRequest.Signature //保存签名供以后使用 156 binary.LittleEndian.PutUint64(recoveredRequest.Signature[5:], 556845463424) //写一些随机数据来破坏签名 157 if err = recoveredRequest.Verify(); err == nil { 158 t.Fatal("Expected Verify to fail on corrupt signature") 159 } 160 161 //从腐败中恢复Bob的签名 162 *recoveredRequest.Signature = savedSignature 163 164 //现在签名没有损坏 165 if err = recoveredRequest.Verify(); err != nil { 166 t.Fatal(err) 167 } 168 169 //重用对象并用我们朋友Charlie的私钥签名 170 if err := recoveredRequest.Sign(charlie); err != nil { 171 t.Fatalf("Error signing with the correct private key: %s", err) 172 } 173 174 //现在,验证应该可以工作,因为这个更新现在属于查理。 175 if err = recoveredRequest.Verify(); err != nil { 176 t.Fatalf("Error verifying that Charlie, can sign a reused request object:%s", err) 177 } 178 179 //混淆查找键以确保验证失败: 180 recoveredRequest.Time = 77999 //这将更改查找键 181 if err = recoveredRequest.Verify(); err == nil { 182 t.Fatalf("Expected Verify to fail since the lookup key has been altered") 183 } 184 } 185 186 func getTestRequest() *Request { 187 return &Request{ 188 Update: *getTestFeedUpdate(), 189 } 190 } 191 192 func TestUpdateChunkSerializationErrorChecking(t *testing.T) { 193 194 //如果块太小,则ParseUpdate测试失败 195 var r Request 196 if err := r.fromChunk(storage.NewChunk(storage.ZeroAddr, make([]byte, minimumUpdateDataLength-1+signatureLength))); err == nil { 197 t.Fatalf("Expected request.fromChunk to fail when chunkData contains less than %d bytes", minimumUpdateDataLength) 198 } 199 200 r = *getTestRequest() 201 202 _, err := r.toChunk() 203 if err == nil { 204 t.Fatal("Expected request.toChunk to fail when there is no data") 205 } 206 r.data = []byte("Al bien hacer jamás le falta premio") //输入任意长度的数据 207 _, err = r.toChunk() 208 if err == nil { 209 t.Fatal("expected request.toChunk to fail when there is no signature") 210 } 211 212 charlie := newCharlieSigner() 213 if err := r.Sign(charlie); err != nil { 214 t.Fatalf("error signing:%s", err) 215 } 216 217 chunk, err := r.toChunk() 218 if err != nil { 219 t.Fatalf("error creating update chunk:%s", err) 220 } 221 222 compareByteSliceToExpectedHex(t, "chunk", chunk.Data(), "0x0000000000000000776f726c64206e657773207265706f72742c20657665727920686f7572000000876a8936a7cd0b79ef0735ad0896c1afe278781ce803000000000019416c206269656e206861636572206a616dc3a173206c652066616c7461207072656d696f5a0ffe0bc27f207cd5b00944c8b9cee93e08b89b5ada777f123ac535189333f174a6a4ca2f43a92c4a477a49d774813c36ce8288552c58e6205b0ac35d0507eb00") 223 224 var recovered Request 225 recovered.fromChunk(chunk) 226 if !reflect.DeepEqual(recovered, r) { 227 t.Fatal("Expected recovered feed update request to equal the original one") 228 } 229 } 230 231 //检查签名地址是否与更新签名者地址匹配 232 func TestReverse(t *testing.T) { 233 234 epoch := lookup.Epoch{ 235 Time: 7888, 236 Level: 6, 237 } 238 239 //生成假时间提供程序 240 timeProvider := &fakeTimeProvider{ 241 currentTime: startTime.Time, 242 } 243 244 //包含私钥的签名者 245 signer := newAliceSigner() 246 247 //设置RPC并创建源处理程序 248 _, _, teardownTest, err := setupTest(timeProvider, signer) 249 if err != nil { 250 t.Fatal(err) 251 } 252 defer teardownTest() 253 254 topic, _ := NewTopic("Cervantes quotes", nil) 255 fd := Feed{ 256 Topic: topic, 257 User: signer.Address(), 258 } 259 260 data := []byte("Donde una puerta se cierra, otra se abre") 261 262 request := new(Request) 263 request.Feed = fd 264 request.Epoch = epoch 265 request.data = data 266 267 //为此请求生成区块键 268 key := request.Addr() 269 270 if err = request.Sign(signer); err != nil { 271 t.Fatal(err) 272 } 273 274 chunk, err := request.toChunk() 275 if err != nil { 276 t.Fatal(err) 277 } 278 279 //检查我们是否可以从更新块的签名中恢复所有者帐户 280 var checkUpdate Request 281 if err := checkUpdate.fromChunk(chunk); err != nil { 282 t.Fatal(err) 283 } 284 checkdigest, err := checkUpdate.GetDigest() 285 if err != nil { 286 t.Fatal(err) 287 } 288 recoveredAddr, err := getUserAddr(checkdigest, *checkUpdate.Signature) 289 if err != nil { 290 t.Fatalf("Retrieve address from signature fail: %v", err) 291 } 292 originalAddr := crypto.PubkeyToAddress(signer.PrivKey.PublicKey) 293 294 //检查从块中检索到的元数据是否与我们提供的元数据匹配 295 if recoveredAddr != originalAddr { 296 t.Fatalf("addresses dont match: %x != %x", originalAddr, recoveredAddr) 297 } 298 299 if !bytes.Equal(key[:], chunk.Address()[:]) { 300 t.Fatalf("Expected chunk key '%x', was '%x'", key, chunk.Address()) 301 } 302 if epoch != checkUpdate.Epoch { 303 t.Fatalf("Expected epoch to be '%s', was '%s'", epoch.String(), checkUpdate.Epoch.String()) 304 } 305 if !bytes.Equal(data, checkUpdate.data) { 306 t.Fatalf("Expected data '%x', was '%x'", data, checkUpdate.data) 307 } 308 } 309