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