signing: ensure we don't break signatures (#2542)

This commit is contained in:
Egon Elbre 2019-07-12 16:41:19 -04:00 committed by GitHub
parent a2418b22af
commit 002d9748ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 911 additions and 109 deletions

View File

@ -14,31 +14,69 @@ import (
// EncodeOrderLimit encodes order limit into bytes for signing. Removes signature from serialized limit.
func EncodeOrderLimit(ctx context.Context, limit *pb.OrderLimit) (_ []byte, err error) {
defer mon.Task()(&ctx)(&err)
signature := limit.SatelliteSignature
limit.SatelliteSignature = nil
out, err := proto.Marshal(limit)
limit.SatelliteSignature = signature
return out, err
// protobuf has problems with serializing types with nullable=false
// this uses a different message for signing, such that the rest of the code
// doesn't have to deal with pointers for those particular fields.
signing := pb.OrderLimitSigning{}
signing.SerialNumber = limit.SerialNumber
signing.SatelliteId = limit.SatelliteId
if limit.DeprecatedUplinkId != nil && !limit.DeprecatedUplinkId.IsZero() {
signing.DeprecatedUplinkId = limit.DeprecatedUplinkId
}
if !limit.UplinkPublicKey.IsZero() {
signing.UplinkPublicKey = &limit.UplinkPublicKey
}
signing.StorageNodeId = limit.StorageNodeId
signing.PieceId = limit.PieceId
signing.Limit = limit.Limit
signing.Action = limit.Action
if !limit.PieceExpiration.IsZero() {
signing.PieceExpiration = &limit.PieceExpiration
}
if !limit.OrderExpiration.IsZero() {
signing.OrderExpiration = &limit.OrderExpiration
}
if !limit.OrderCreation.IsZero() {
signing.OrderCreation = &limit.OrderCreation
}
signing.SatelliteAddress = limit.SatelliteAddress
return proto.Marshal(&signing)
}
// EncodeOrder encodes order into bytes for signing. Removes signature from serialized order.
func EncodeOrder(ctx context.Context, order *pb.Order) (_ []byte, err error) {
defer mon.Task()(&ctx)(&err)
signature := order.UplinkSignature
order.UplinkSignature = nil
out, err := proto.Marshal(order)
order.UplinkSignature = signature
return out, err
// protobuf has problems with serializing types with nullable=false
// this uses a different message for signing, such that the rest of the code
// doesn't have to deal with pointers for those particular fields.
signing := pb.OrderSigning{}
signing.SerialNumber = order.SerialNumber
signing.Amount = order.Amount
return proto.Marshal(&signing)
}
// EncodePieceHash encodes piece hash into bytes for signing. Removes signature from serialized hash.
func EncodePieceHash(ctx context.Context, hash *pb.PieceHash) (_ []byte, err error) {
defer mon.Task()(&ctx)(&err)
signature := hash.Signature
hash.Signature = nil
out, err := proto.Marshal(hash)
hash.Signature = signature
return out, err
// protobuf has problems with serializing types with nullable=false
// this uses a different message for signing, such that the rest of the code
// doesn't have to deal with pointers for those particular fields.
signing := pb.PieceHashSigning{}
signing.PieceId = hash.PieceId
signing.Hash = hash.Hash
signing.PieceSize = hash.PieceSize
if !hash.Timestamp.IsZero() {
signing.Timestamp = &hash.Timestamp
}
return proto.Marshal(&signing)
}
// EncodeVoucher encodes voucher into bytes for signing.

View File

@ -1,39 +0,0 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package signing_test
import (
"encoding/hex"
"testing"
"github.com/gogo/protobuf/proto"
"github.com/stretchr/testify/require"
"storj.io/storj/pkg/pb"
)
func TestOrderSerialization(t *testing.T) {
t.Skip("broken")
orderLimitBytes, err := hex.DecodeString(`0A1027C6C39653A24B94BA560A7951698FF312209BD465AB990C1E62C7B99FEE63E71761FF1A7ECD951D502CE95F4A41D4C91A001A209BD465AB990C1E62C7B99FEE63E71761FF1A7ECD951D502CE95F4A41D4C91A0022209A27D4F09F85609E85B861B11F95C785899DC394FEC6BD4E303C502C3B7E2B002A20A86125ACD1B98E7262F9D38D9B27204DAF4E44092B0FBA786474B4754D45753330800838034A0C08B1E1A2EA0510AEF4AED70352463044022035EE84CAE8FE8CEBA52B2C1BD7A3891FA049557D5C4DE6BDEDAF5C92E2D004FA0220170DA89541EF962538763B0B55FDD04F14A623E118F55601FD8FA7DF266A374F`)
require.NoError(t, err)
orderBytes, err := hex.DecodeString(`0A1027C6C39653A24B94BA560A7951698FF31080081A473045022100BB7A53C2835BF5CAC59479C7A3A17447AC9D3DAE894B20849FDDF9E3533F173202207910685EB70107BFF73A2F94AF345369E51B35208941EB5CE903E48EFFB41642`)
require.NoError(t, err)
orderLimit := pb.OrderLimit{}
err = proto.Unmarshal(orderLimitBytes, &orderLimit)
require.NoError(t, err)
orderLimitMarshaled, err := proto.Marshal(&orderLimit)
require.NoError(t, err)
require.Equal(t, orderLimitBytes, orderLimitMarshaled, "order limit marshaling changed")
order := pb.Order{}
err = proto.Unmarshal(orderBytes, &order)
require.NoError(t, err)
orderBytesMarshaled, err := proto.Marshal(&order)
require.NoError(t, err)
require.Equal(t, orderBytes, orderBytesMarshaled, "order marshaling changed")
}

View File

@ -0,0 +1,208 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package signing_test
import (
"encoding/hex"
"testing"
"github.com/gogo/protobuf/proto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"storj.io/storj/internal/testcontext"
"storj.io/storj/pkg/auth/signing"
"storj.io/storj/pkg/identity"
"storj.io/storj/pkg/pb"
"storj.io/storj/pkg/storj"
)
func TestOrderLimitVerification(t *testing.T) {
ctx := testcontext.New(t)
defer ctx.Cleanup()
signer, err := identity.FullIdentityFromPEM(
[]byte("-----BEGIN CERTIFICATE-----\nMIIBYjCCAQigAwIBAgIRAMM/5SHfNFMLl9uTAAQEoZAwCgYIKoZIzj0EAwIwEDEO\nMAwGA1UEChMFU3RvcmowIhgPMDAwMTAxMDEwMDAwMDBaGA8wMDAxMDEwMTAwMDAw\nMFowEDEOMAwGA1UEChMFU3RvcmowWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS/\n9wOAe42DV90jcRJMMeGe9os528RNJbMthDMkAn58KyOH87Rvlz0uCRnhhk3AbDE+\nXXHfEyed/HPFEMxJwmlGoz8wPTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYI\nKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwCgYIKoZIzj0EAwIDSAAw\nRQIhALl9VMhM6NFnPblqOsIHOznsKr0OfQREf/+GSk/t8McsAiAxyOYg3IlB9iA0\nq/pD+qUwXuS+NFyVGOhgdNDFT3amOA==\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIBWzCCAQGgAwIBAgIRAMfle+YJvbpRwr+FqiTrRyswCgYIKoZIzj0EAwIwEDEO\nMAwGA1UEChMFU3RvcmowIhgPMDAwMTAxMDEwMDAwMDBaGA8wMDAxMDEwMTAwMDAw\nMFowEDEOMAwGA1UEChMFU3RvcmowWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARL\nO4n2UCp66X/MY5AzhZsfbBYOBw81Dv8V3y1BXXtbHNsUWNY8RT7r5FSTuLHsaXwq\nTwHdU05bjgnLZT/XdwqaozgwNjAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0lBAwwCgYI\nKwYBBQUHAwEwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEA2vce\nasP0sjt6QRJNkgdV/IONJCF0IGgmsCoogCbh9ggCIA3mHgivRBId7sSAU4UUPxpB\nOOfce7bVuJlxvsnNfkkz\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIBWjCCAQCgAwIBAgIQdzcArqh7Yp9aGiiJXM4+8TAKBggqhkjOPQQDAjAQMQ4w\nDAYDVQQKEwVTdG9yajAiGA8wMDAxMDEwMTAwMDAwMFoYDzAwMDEwMTAxMDAwMDAw\nWjAQMQ4wDAYDVQQKEwVTdG9yajBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABM/W\nTxYhs/yGKSg8+Hb2Z/NB2KJef+fWkq7mHl7vhD9JgFwVMowMEFtKOCAhZxLBZD47\nxhYDhHBv4vrLLS+m3wGjODA2MA4GA1UdDwEB/wQEAwICBDATBgNVHSUEDDAKBggr\nBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIC+gM/sI\nXXHq5jJmolw50KKVHlqaqpdxjxJ/6x8oqTHWAiEA1w9EbqPXQ5u/oM+ODf1TBkms\nN9NfnJsY1I2A3NKEvq8=\n-----END CERTIFICATE-----\n"),
[]byte("-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgzsFsVqt/GdqQlIIJ\nHH2VQNndv1A1fTk/35VPNzLW04ehRANCAATzXrIfcBZAHHxPdFD2PFRViRwe6eWf\nQipaF4iXQmHAW79X4mDx0BibjFfvmzurnYSlyIMZn3jp9RzbLMfnA10C\n-----END PRIVATE KEY-----\n"),
)
require.NoError(t, err)
signee := signing.SignerFromFullIdentity(signer)
type Hex struct {
Unsigned string
Signed string
}
hexes := []Hex{
{ // 385c0467
Unsigned: "0a1052fdfc072182654f163f5f0f9a621d7212200ed28abb2813e184a1e98b0f6605c4911ea468c7e8433eb583e0fca7ceac30001a209566c74d10037c4d7bbb0407d1e2c64981855ad8681d0d86d1e91e001679390022206694d2c422acd208a0072939487f6999eb9d18a44784045d87f3c67cf22746002a2095af5a25367951baa2ff6cd471c483f15fb90badb37c5821b6d95526a41a950430904e3802420c08a1dba2e90510e0a1b3c6014a0c08a1dba2e90510e0a1b3c6015a1f121d68747470733a2f2f736174656c6c6974652e6578616d706c652e636f6d",
Signed: "0a1052fdfc072182654f163f5f0f9a621d7212200ed28abb2813e184a1e98b0f6605c4911ea468c7e8433eb583e0fca7ceac30001a209566c74d10037c4d7bbb0407d1e2c64981855ad8681d0d86d1e91e001679390022206694d2c422acd208a0072939487f6999eb9d18a44784045d87f3c67cf22746002a2095af5a25367951baa2ff6cd471c483f15fb90badb37c5821b6d95526a41a950430904e3802420c08a1dba2e90510e0a1b3c6014a0c08a1dba2e90510e0a1b3c60152473045022100ada5fc332dfbd607216e961bede421e43e2e336acab8eab2244f5e3a696ede720220365e78e738c19fc9d3cb26b061dcf6439ea702cb0ef1408cf7aeb27cabee4cc45a1f121d68747470733a2f2f736174656c6c6974652e6578616d706c652e636f6d",
},
{ // 385c0467 without satellite address
Unsigned: "0a1052fdfc072182654f163f5f0f9a621d7212200ed28abb2813e184a1e98b0f6605c4911ea468c7e8433eb583e0fca7ceac30001a209566c74d10037c4d7bbb0407d1e2c64981855ad8681d0d86d1e91e001679390022206694d2c422acd208a0072939487f6999eb9d18a44784045d87f3c67cf22746002a2095af5a25367951baa2ff6cd471c483f15fb90badb37c5821b6d95526a41a950430904e3802420c08a1dba2e90510e0a1b3c6014a0c08a1dba2e90510e0a1b3c601",
Signed: "0a1052fdfc072182654f163f5f0f9a621d7212200ed28abb2813e184a1e98b0f6605c4911ea468c7e8433eb583e0fca7ceac30001a209566c74d10037c4d7bbb0407d1e2c64981855ad8681d0d86d1e91e001679390022206694d2c422acd208a0072939487f6999eb9d18a44784045d87f3c67cf22746002a2095af5a25367951baa2ff6cd471c483f15fb90badb37c5821b6d95526a41a950430904e3802420c08a1dba2e90510e0a1b3c6014a0c08a1dba2e90510e0a1b3c60152473045022100a2e7849a4cb93e6bbc591949f93a5e97d9b1392a5770667afc634389355e094102200bfa72531afc9359181f7fc5181e387a03dea8234f74a7d7c44ca3aa0c5ab21d",
},
{ // 385c0467 without piece expiration
Unsigned: "0a1052fdfc072182654f163f5f0f9a621d7212200ed28abb2813e184a1e98b0f6605c4911ea468c7e8433eb583e0fca7ceac30001a209566c74d10037c4d7bbb0407d1e2c64981855ad8681d0d86d1e91e001679390022206694d2c422acd208a0072939487f6999eb9d18a44784045d87f3c67cf22746002a2095af5a25367951baa2ff6cd471c483f15fb90badb37c5821b6d95526a41a950430904e38024a0c08a1dba2e90510e0a1b3c6015a1f121d68747470733a2f2f736174656c6c6974652e6578616d706c652e636f6d",
Signed: "0a1052fdfc072182654f163f5f0f9a621d7212200ed28abb2813e184a1e98b0f6605c4911ea468c7e8433eb583e0fca7ceac30001a209566c74d10037c4d7bbb0407d1e2c64981855ad8681d0d86d1e91e001679390022206694d2c422acd208a0072939487f6999eb9d18a44784045d87f3c67cf22746002a2095af5a25367951baa2ff6cd471c483f15fb90badb37c5821b6d95526a41a950430904e38024a0c08a1dba2e90510e0a1b3c6015246304402206656347801dd620f00a86c848a06eb3369dd552b1ff905b0d4424adeb9fdb3c502201332be7725c07d84f87aefda94be83f7b3513eeeb3af7b0953e55276343a8a685a1f121d68747470733a2f2f736174656c6c6974652e6578616d706c652e636f6d",
},
{ // public piece key
Unsigned: "0a1052fdfc072182654f163f5f0f9a621d7212200ed28abb2813e184a1e98b0f6605c4911ea468c7e8433eb583e0fca7ceac300022209566c74d10037c4d7bbb0407d1e2c64981855ad8681d0d86d1e91e00167939002a206694d2c422acd208a0072939487f6999eb9d18a44784045d87f3c67cf22746e930904e3802420c0899eea2e9051090b98af6024a0c0899eea2e9051090b98af6025a1f121d68747470733a2f2f736174656c6c6974652e6578616d706c652e636f6d6a20fd302f9f1acd1f90f5b59d8fb5d5b2d8d3d62210d4efa8647bb7a177ece96dcc",
Signed: "0a1052fdfc072182654f163f5f0f9a621d7212200ed28abb2813e184a1e98b0f6605c4911ea468c7e8433eb583e0fca7ceac300022209566c74d10037c4d7bbb0407d1e2c64981855ad8681d0d86d1e91e00167939002a206694d2c422acd208a0072939487f6999eb9d18a44784045d87f3c67cf22746e930904e3802420c0899eea2e9051090b98af6024a0c0899eea2e9051090b98af60252483046022100a4c53b654edb2ec19780b1c06d695c8b0bb0850edab1d2e999e784deb8f5359c0221008ad8eb26f4d6570c3dfb82faac0890b5212e30c7ad5a301220f729e3627205425a1f121d68747470733a2f2f736174656c6c6974652e6578616d706c652e636f6d620b088092b8c398feffffff016a20fd302f9f1acd1f90f5b59d8fb5d5b2d8d3d62210d4efa8647bb7a177ece96dcc",
},
{ // public piece key, without piece expiration
Unsigned: "0a1052fdfc072182654f163f5f0f9a621d7212200ed28abb2813e184a1e98b0f6605c4911ea468c7e8433eb583e0fca7ceac300022209566c74d10037c4d7bbb0407d1e2c64981855ad8681d0d86d1e91e00167939002a206694d2c422acd208a0072939487f6999eb9d18a44784045d87f3c67cf22746e930904e38024a0c0899eea2e9051090b98af6025a1f121d68747470733a2f2f736174656c6c6974652e6578616d706c652e636f6d6a20fd302f9f1acd1f90f5b59d8fb5d5b2d8d3d62210d4efa8647bb7a177ece96dcc",
Signed: "0a1052fdfc072182654f163f5f0f9a621d7212200ed28abb2813e184a1e98b0f6605c4911ea468c7e8433eb583e0fca7ceac300022209566c74d10037c4d7bbb0407d1e2c64981855ad8681d0d86d1e91e00167939002a206694d2c422acd208a0072939487f6999eb9d18a44784045d87f3c67cf22746e930904e3802420b088092b8c398feffffff014a0c0899eea2e9051090b98af602524630440220751ae9aa91e78cf5fc858419675cb1148886acfd313c4126870d86c938675e2002206bf29b5efe3752a348446d54d3f10273bc1d582b54cbc2341db7e11508e522085a1f121d68747470733a2f2f736174656c6c6974652e6578616d706c652e636f6d620b088092b8c398feffffff016a20fd302f9f1acd1f90f5b59d8fb5d5b2d8d3d62210d4efa8647bb7a177ece96dcc",
},
}
for _, test := range hexes {
unsignedBytes, err := hex.DecodeString(test.Unsigned)
require.NoError(t, err)
signedBytes, err := hex.DecodeString(test.Signed)
require.NoError(t, err)
orderLimit := pb.OrderLimit{}
err = proto.Unmarshal(signedBytes, &orderLimit)
require.NoError(t, err)
err = signing.VerifyOrderLimitSignature(ctx, signee, &orderLimit)
assert.NoError(t, err)
encoded, err := signing.EncodeOrderLimit(ctx, &orderLimit)
require.NoError(t, err)
assert.Equal(t, unsignedBytes, encoded)
}
}
func TestOrderVerification(t *testing.T) {
ctx := testcontext.New(t)
defer ctx.Cleanup()
signer, err := identity.FullIdentityFromPEM(
[]byte("-----BEGIN CERTIFICATE-----\nMIIBYjCCAQigAwIBAgIRAMM/5SHfNFMLl9uTAAQEoZAwCgYIKoZIzj0EAwIwEDEO\nMAwGA1UEChMFU3RvcmowIhgPMDAwMTAxMDEwMDAwMDBaGA8wMDAxMDEwMTAwMDAw\nMFowEDEOMAwGA1UEChMFU3RvcmowWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS/\n9wOAe42DV90jcRJMMeGe9os528RNJbMthDMkAn58KyOH87Rvlz0uCRnhhk3AbDE+\nXXHfEyed/HPFEMxJwmlGoz8wPTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYI\nKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwCgYIKoZIzj0EAwIDSAAw\nRQIhALl9VMhM6NFnPblqOsIHOznsKr0OfQREf/+GSk/t8McsAiAxyOYg3IlB9iA0\nq/pD+qUwXuS+NFyVGOhgdNDFT3amOA==\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIBWzCCAQGgAwIBAgIRAMfle+YJvbpRwr+FqiTrRyswCgYIKoZIzj0EAwIwEDEO\nMAwGA1UEChMFU3RvcmowIhgPMDAwMTAxMDEwMDAwMDBaGA8wMDAxMDEwMTAwMDAw\nMFowEDEOMAwGA1UEChMFU3RvcmowWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARL\nO4n2UCp66X/MY5AzhZsfbBYOBw81Dv8V3y1BXXtbHNsUWNY8RT7r5FSTuLHsaXwq\nTwHdU05bjgnLZT/XdwqaozgwNjAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0lBAwwCgYI\nKwYBBQUHAwEwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEA2vce\nasP0sjt6QRJNkgdV/IONJCF0IGgmsCoogCbh9ggCIA3mHgivRBId7sSAU4UUPxpB\nOOfce7bVuJlxvsnNfkkz\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIBWjCCAQCgAwIBAgIQdzcArqh7Yp9aGiiJXM4+8TAKBggqhkjOPQQDAjAQMQ4w\nDAYDVQQKEwVTdG9yajAiGA8wMDAxMDEwMTAwMDAwMFoYDzAwMDEwMTAxMDAwMDAw\nWjAQMQ4wDAYDVQQKEwVTdG9yajBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABM/W\nTxYhs/yGKSg8+Hb2Z/NB2KJef+fWkq7mHl7vhD9JgFwVMowMEFtKOCAhZxLBZD47\nxhYDhHBv4vrLLS+m3wGjODA2MA4GA1UdDwEB/wQEAwICBDATBgNVHSUEDDAKBggr\nBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIC+gM/sI\nXXHq5jJmolw50KKVHlqaqpdxjxJ/6x8oqTHWAiEA1w9EbqPXQ5u/oM+ODf1TBkms\nN9NfnJsY1I2A3NKEvq8=\n-----END CERTIFICATE-----\n"),
[]byte("-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgzsFsVqt/GdqQlIIJ\nHH2VQNndv1A1fTk/35VPNzLW04ehRANCAATzXrIfcBZAHHxPdFD2PFRViRwe6eWf\nQipaF4iXQmHAW79X4mDx0BibjFfvmzurnYSlyIMZn3jp9RzbLMfnA10C\n-----END PRIVATE KEY-----\n"),
)
require.NoError(t, err)
signee := signing.SignerFromFullIdentity(signer)
type Hex struct {
Unsigned string
Signed string
}
hexes := []Hex{
{ // commmit 385c0467
Unsigned: "0a1068d2d6c52f5054e2d0836bf84c7174cb10e807",
Signed: "0a1068d2d6c52f5054e2d0836bf84c7174cb10e8071a473045022007800e9843f6ac56ae0a136406b8c685c552c7280e45761492ab521e1a27a984022100a535e3d9de1ba7778148186b319bd2857d8e2a7037a75db99b8c62eb18ed7646",
},
}
for _, test := range hexes {
unsignedBytes, err := hex.DecodeString(test.Unsigned)
require.NoError(t, err)
signedBytes, err := hex.DecodeString(test.Signed)
require.NoError(t, err)
order := pb.Order{}
err = proto.Unmarshal(signedBytes, &order)
require.NoError(t, err)
err = signing.VerifyOrderSignature(ctx, signee, &order)
assert.NoError(t, err)
encoded, err := signing.EncodeOrder(ctx, &order)
require.NoError(t, err)
assert.Equal(t, unsignedBytes, encoded)
}
}
func TestUplinkOrderVerification(t *testing.T) {
ctx := testcontext.New(t)
defer ctx.Cleanup()
publicKeyBytes, _ := hex.DecodeString("01eaebcb418cd629d4c01f365f33006c9de3ce70cf04da76c39cdc993f48fe53")
privateKeyBytes, _ := hex.DecodeString("afefcccadb3d17b1f241b7c83f88c088b54c01b5a25409c13cbeca6bfa22b06901eaebcb418cd629d4c01f365f33006c9de3ce70cf04da76c39cdc993f48fe53")
publicKey, err := storj.PiecePublicKeyFromBytes(publicKeyBytes)
require.NoError(t, err)
privateKey, err := storj.PiecePrivateKeyFromBytes(privateKeyBytes)
require.NoError(t, err)
_ = privateKey
type Hex struct {
Unsigned string
Signed string
}
hexes := []Hex{
{
Unsigned: "0a1052fdfc072182654f163f5f0f9a621d7210e807",
Signed: "0a1052fdfc072182654f163f5f0f9a621d7210e8071a4017871739c3d458737bf24bf214a7387552b18ad75afc3636974cb0d768901a85446954d59a291dde7fde0c648a242863891f543121d4633778c5b6057e62e607",
},
}
for _, test := range hexes {
unsignedBytes, err := hex.DecodeString(test.Unsigned)
require.NoError(t, err)
signedBytes, err := hex.DecodeString(test.Signed)
require.NoError(t, err)
order := pb.Order{}
err = proto.Unmarshal(signedBytes, &order)
require.NoError(t, err)
err = signing.VerifyUplinkOrderSignature(ctx, publicKey, &order)
assert.NoError(t, err)
encoded, err := signing.EncodeOrder(ctx, &order)
require.NoError(t, err)
assert.Equal(t, unsignedBytes, encoded)
}
}
func TestPieceHashVerification(t *testing.T) {
ctx := testcontext.New(t)
defer ctx.Cleanup()
publicKeyBytes, _ := hex.DecodeString("01eaebcb418cd629d4c01f365f33006c9de3ce70cf04da76c39cdc993f48fe53")
privateKeyBytes, _ := hex.DecodeString("afefcccadb3d17b1f241b7c83f88c088b54c01b5a25409c13cbeca6bfa22b06901eaebcb418cd629d4c01f365f33006c9de3ce70cf04da76c39cdc993f48fe53")
publicKey, err := storj.PiecePublicKeyFromBytes(publicKeyBytes)
require.NoError(t, err)
privateKey, err := storj.PiecePrivateKeyFromBytes(privateKeyBytes)
require.NoError(t, err)
_ = privateKey
type Hex struct {
Unsigned string
Signed string
}
hexes := []Hex{
{
Unsigned: "0a2052fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c649122081855ad8681d0d86d1e91e00167939cb6694d2c422acd208a0072939487f699920e8072a0c08ba92a3e90510c89afe8202",
Signed: "0a2052fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c649122081855ad8681d0d86d1e91e00167939cb6694d2c422acd208a0072939487f69991a40757ff5203925e02c246babdd91c9321265a158d19c99258493fe5cb6482d4bbbb97dea35227ba7b693a3c878e47d8392fc78388e225b541b98c799be7fce3c0720e8072a0c08ba92a3e90510c89afe8202",
},
}
for _, test := range hexes {
unsignedBytes, err := hex.DecodeString(test.Unsigned)
require.NoError(t, err)
signedBytes, err := hex.DecodeString(test.Signed)
require.NoError(t, err)
hash := pb.PieceHash{}
err = proto.Unmarshal(signedBytes, &hash)
require.NoError(t, err)
err = signing.VerifyUplinkPieceHashSignature(ctx, publicKey, &hash)
assert.NoError(t, err)
encoded, err := signing.EncodePieceHash(ctx, &hash)
require.NoError(t, err)
assert.Equal(t, unsignedBytes, encoded)
}
}

View File

@ -0,0 +1,65 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package pb_test
import (
fmt "fmt"
"reflect"
"sort"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"storj.io/storj/pkg/pb"
)
func TestCompatibility(t *testing.T) {
// when these fail, the X and XSigning definitions are out of sync
// remember to update the conversions in auth/signing
check(t, pb.OrderLimit{}, pb.OrderLimitSigning{})
check(t, pb.Order{}, pb.OrderSigning{})
check(t, pb.PieceHash{}, pb.PieceHashSigning{})
}
func check(t *testing.T, a, b interface{}) {
afields := fields(a)
bfields := fields(b)
assert.Equal(t, afields, bfields, fmt.Sprintf("%T and %T definitions don't match", a, b))
}
type Field struct {
Name string
Type string
Index string
}
func fields(v interface{}) []Field {
t := reflect.ValueOf(v).Type()
if t.Kind() != reflect.Struct {
panic(t.Kind())
}
var fields []Field
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
tag := f.Tag.Get("protobuf")
if tag == "" {
continue
}
tags := strings.Split(tag, ",")
fields = append(fields, Field{
Name: f.Name,
Type: tags[0],
Index: tags[1],
})
}
sort.Slice(fields, func(i, k int) bool {
return fields[i].Name < fields[k].Name
})
return fields
}

View File

@ -92,7 +92,7 @@ func (x SettlementResponse_Status) String() string {
}
func (SettlementResponse_Status) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_e0f5d4cf0fc9e41b, []int{4, 0}
return fileDescriptor_e0f5d4cf0fc9e41b, []int{7, 0}
}
// OrderLimit is provided by satellite to execute specific action on storage node within some limits
@ -197,6 +197,113 @@ func (m *OrderLimit) GetSatelliteAddress() *NodeAddress {
return nil
}
// OrderLimitSigning provides OrderLimit signing serialization
//
// It is never used for sending across the network, it is
// used in signing to ensure that nullable=false fields get handled properly.
// Its purpose is to solidify the format of how we serialize for
// signing, to handle some backwards compatibility considerations.
type OrderLimitSigning struct {
// unique serial to avoid replay attacks
SerialNumber SerialNumber `protobuf:"bytes,1,opt,name=serial_number,json=serialNumber,proto3,customtype=SerialNumber" json:"serial_number"`
// satellite who issued this order limit allowing orderer to do the specified action
SatelliteId NodeID `protobuf:"bytes,2,opt,name=satellite_id,json=satelliteId,proto3,customtype=NodeID" json:"satellite_id"`
// uplink who requested or whom behalf the order limit to do an action
DeprecatedUplinkId *NodeID `protobuf:"bytes,3,opt,name=deprecated_uplink_id,json=deprecatedUplinkId,proto3,customtype=NodeID" json:"deprecated_uplink_id,omitempty"`
// public key that will be used to sign orders and piece hash
UplinkPublicKey *PiecePublicKey `protobuf:"bytes,13,opt,name=uplink_public_key,json=uplinkPublicKey,proto3,customtype=PiecePublicKey" json:"uplink_public_key,omitempty"`
// storage node who can re claimthe order limit specified by serial
StorageNodeId NodeID `protobuf:"bytes,4,opt,name=storage_node_id,json=storageNodeId,proto3,customtype=NodeID" json:"storage_node_id"`
// piece which is allowed to be touched
PieceId PieceID `protobuf:"bytes,5,opt,name=piece_id,json=pieceId,proto3,customtype=PieceID" json:"piece_id"`
// limit in bytes how much can be changed
Limit int64 `protobuf:"varint,6,opt,name=limit,proto3" json:"limit,omitempty"`
Action PieceAction `protobuf:"varint,7,opt,name=action,proto3,enum=orders.PieceAction" json:"action,omitempty"`
PieceExpiration *time.Time `protobuf:"bytes,8,opt,name=piece_expiration,json=pieceExpiration,proto3,stdtime" json:"piece_expiration,omitempty"`
OrderExpiration *time.Time `protobuf:"bytes,9,opt,name=order_expiration,json=orderExpiration,proto3,stdtime" json:"order_expiration,omitempty"`
OrderCreation *time.Time `protobuf:"bytes,12,opt,name=order_creation,json=orderCreation,proto3,stdtime" json:"order_creation,omitempty"`
SatelliteSignature []byte `protobuf:"bytes,10,opt,name=satellite_signature,json=satelliteSignature,proto3" json:"satellite_signature,omitempty"`
// satellites aren't necessarily discoverable in kademlia. this allows
// a storage node to find a satellite and handshake with it to get its key.
SatelliteAddress *NodeAddress `protobuf:"bytes,11,opt,name=satellite_address,json=satelliteAddress,proto3" json:"satellite_address,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *OrderLimitSigning) Reset() { *m = OrderLimitSigning{} }
func (m *OrderLimitSigning) String() string { return proto.CompactTextString(m) }
func (*OrderLimitSigning) ProtoMessage() {}
func (*OrderLimitSigning) Descriptor() ([]byte, []int) {
return fileDescriptor_e0f5d4cf0fc9e41b, []int{1}
}
func (m *OrderLimitSigning) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_OrderLimitSigning.Unmarshal(m, b)
}
func (m *OrderLimitSigning) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_OrderLimitSigning.Marshal(b, m, deterministic)
}
func (m *OrderLimitSigning) XXX_Merge(src proto.Message) {
xxx_messageInfo_OrderLimitSigning.Merge(m, src)
}
func (m *OrderLimitSigning) XXX_Size() int {
return xxx_messageInfo_OrderLimitSigning.Size(m)
}
func (m *OrderLimitSigning) XXX_DiscardUnknown() {
xxx_messageInfo_OrderLimitSigning.DiscardUnknown(m)
}
var xxx_messageInfo_OrderLimitSigning proto.InternalMessageInfo
func (m *OrderLimitSigning) GetLimit() int64 {
if m != nil {
return m.Limit
}
return 0
}
func (m *OrderLimitSigning) GetAction() PieceAction {
if m != nil {
return m.Action
}
return PieceAction_INVALID
}
func (m *OrderLimitSigning) GetPieceExpiration() *time.Time {
if m != nil {
return m.PieceExpiration
}
return nil
}
func (m *OrderLimitSigning) GetOrderExpiration() *time.Time {
if m != nil {
return m.OrderExpiration
}
return nil
}
func (m *OrderLimitSigning) GetOrderCreation() *time.Time {
if m != nil {
return m.OrderCreation
}
return nil
}
func (m *OrderLimitSigning) GetSatelliteSignature() []byte {
if m != nil {
return m.SatelliteSignature
}
return nil
}
func (m *OrderLimitSigning) GetSatelliteAddress() *NodeAddress {
if m != nil {
return m.SatelliteAddress
}
return nil
}
// Order is a one step of fullfilling Amount number of bytes from an OrderLimit with SerialNumber
type Order struct {
// serial of the order limit that was signed
@ -214,7 +321,7 @@ func (m *Order) Reset() { *m = Order{} }
func (m *Order) String() string { return proto.CompactTextString(m) }
func (*Order) ProtoMessage() {}
func (*Order) Descriptor() ([]byte, []int) {
return fileDescriptor_e0f5d4cf0fc9e41b, []int{1}
return fileDescriptor_e0f5d4cf0fc9e41b, []int{2}
}
func (m *Order) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Order.Unmarshal(m, b)
@ -248,6 +355,62 @@ func (m *Order) GetUplinkSignature() []byte {
return nil
}
// OrderSigning provides Order signing format
//
// It is never used for sending across the network, it is
// used in signing to ensure that nullable=false fields get handled properly.
// Its purpose is to solidify the format of how we serialize for
// signing, to handle some backwards compatibility considerations.
type OrderSigning struct {
// serial of the order limit that was signed
SerialNumber SerialNumber `protobuf:"bytes,1,opt,name=serial_number,json=serialNumber,proto3,customtype=SerialNumber" json:"serial_number"`
// amount to be signed for
Amount int64 `protobuf:"varint,2,opt,name=amount,proto3" json:"amount,omitempty"`
// signature
UplinkSignature []byte `protobuf:"bytes,3,opt,name=uplink_signature,json=uplinkSignature,proto3" json:"uplink_signature,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *OrderSigning) Reset() { *m = OrderSigning{} }
func (m *OrderSigning) String() string { return proto.CompactTextString(m) }
func (*OrderSigning) ProtoMessage() {}
func (*OrderSigning) Descriptor() ([]byte, []int) {
return fileDescriptor_e0f5d4cf0fc9e41b, []int{3}
}
func (m *OrderSigning) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_OrderSigning.Unmarshal(m, b)
}
func (m *OrderSigning) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_OrderSigning.Marshal(b, m, deterministic)
}
func (m *OrderSigning) XXX_Merge(src proto.Message) {
xxx_messageInfo_OrderSigning.Merge(m, src)
}
func (m *OrderSigning) XXX_Size() int {
return xxx_messageInfo_OrderSigning.Size(m)
}
func (m *OrderSigning) XXX_DiscardUnknown() {
xxx_messageInfo_OrderSigning.DiscardUnknown(m)
}
var xxx_messageInfo_OrderSigning proto.InternalMessageInfo
func (m *OrderSigning) GetAmount() int64 {
if m != nil {
return m.Amount
}
return 0
}
func (m *OrderSigning) GetUplinkSignature() []byte {
if m != nil {
return m.UplinkSignature
}
return nil
}
type PieceHash struct {
// piece id
PieceId PieceID `protobuf:"bytes,1,opt,name=piece_id,json=pieceId,proto3,customtype=PieceID" json:"piece_id"`
@ -268,7 +431,7 @@ func (m *PieceHash) Reset() { *m = PieceHash{} }
func (m *PieceHash) String() string { return proto.CompactTextString(m) }
func (*PieceHash) ProtoMessage() {}
func (*PieceHash) Descriptor() ([]byte, []int) {
return fileDescriptor_e0f5d4cf0fc9e41b, []int{2}
return fileDescriptor_e0f5d4cf0fc9e41b, []int{4}
}
func (m *PieceHash) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_PieceHash.Unmarshal(m, b)
@ -316,6 +479,80 @@ func (m *PieceHash) GetSignature() []byte {
return nil
}
// PieceHashSigning provides piece hash signing format.
//
// It is never used for sending across the network, it is
// used in signing to ensure that nullable=false fields get handled properly.
// Its purpose is to solidify the format of how we serialize for
// signing, to handle some backwards compatibility considerations.
type PieceHashSigning struct {
// piece id
PieceId PieceID `protobuf:"bytes,1,opt,name=piece_id,json=pieceId,proto3,customtype=PieceID" json:"piece_id"`
// hash of the piece that was/is uploaded
Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"`
// size of uploaded piece
PieceSize int64 `protobuf:"varint,4,opt,name=piece_size,json=pieceSize,proto3" json:"piece_size,omitempty"`
// timestamp when upload occurred
Timestamp *time.Time `protobuf:"bytes,5,opt,name=timestamp,proto3,stdtime" json:"timestamp,omitempty"`
// signature either satellite or storage node
Signature []byte `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *PieceHashSigning) Reset() { *m = PieceHashSigning{} }
func (m *PieceHashSigning) String() string { return proto.CompactTextString(m) }
func (*PieceHashSigning) ProtoMessage() {}
func (*PieceHashSigning) Descriptor() ([]byte, []int) {
return fileDescriptor_e0f5d4cf0fc9e41b, []int{5}
}
func (m *PieceHashSigning) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_PieceHashSigning.Unmarshal(m, b)
}
func (m *PieceHashSigning) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_PieceHashSigning.Marshal(b, m, deterministic)
}
func (m *PieceHashSigning) XXX_Merge(src proto.Message) {
xxx_messageInfo_PieceHashSigning.Merge(m, src)
}
func (m *PieceHashSigning) XXX_Size() int {
return xxx_messageInfo_PieceHashSigning.Size(m)
}
func (m *PieceHashSigning) XXX_DiscardUnknown() {
xxx_messageInfo_PieceHashSigning.DiscardUnknown(m)
}
var xxx_messageInfo_PieceHashSigning proto.InternalMessageInfo
func (m *PieceHashSigning) GetHash() []byte {
if m != nil {
return m.Hash
}
return nil
}
func (m *PieceHashSigning) GetPieceSize() int64 {
if m != nil {
return m.PieceSize
}
return 0
}
func (m *PieceHashSigning) GetTimestamp() *time.Time {
if m != nil {
return m.Timestamp
}
return nil
}
func (m *PieceHashSigning) GetSignature() []byte {
if m != nil {
return m.Signature
}
return nil
}
type SettlementRequest struct {
Limit *OrderLimit `protobuf:"bytes,1,opt,name=limit,proto3" json:"limit,omitempty"`
Order *Order `protobuf:"bytes,2,opt,name=order,proto3" json:"order,omitempty"`
@ -328,7 +565,7 @@ func (m *SettlementRequest) Reset() { *m = SettlementRequest{} }
func (m *SettlementRequest) String() string { return proto.CompactTextString(m) }
func (*SettlementRequest) ProtoMessage() {}
func (*SettlementRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_e0f5d4cf0fc9e41b, []int{3}
return fileDescriptor_e0f5d4cf0fc9e41b, []int{6}
}
func (m *SettlementRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SettlementRequest.Unmarshal(m, b)
@ -374,7 +611,7 @@ func (m *SettlementResponse) Reset() { *m = SettlementResponse{} }
func (m *SettlementResponse) String() string { return proto.CompactTextString(m) }
func (*SettlementResponse) ProtoMessage() {}
func (*SettlementResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_e0f5d4cf0fc9e41b, []int{4}
return fileDescriptor_e0f5d4cf0fc9e41b, []int{7}
}
func (m *SettlementResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SettlementResponse.Unmarshal(m, b)
@ -405,8 +642,11 @@ func init() {
proto.RegisterEnum("orders.PieceAction", PieceAction_name, PieceAction_value)
proto.RegisterEnum("orders.SettlementResponse_Status", SettlementResponse_Status_name, SettlementResponse_Status_value)
proto.RegisterType((*OrderLimit)(nil), "orders.OrderLimit")
proto.RegisterType((*OrderLimitSigning)(nil), "orders.OrderLimitSigning")
proto.RegisterType((*Order)(nil), "orders.Order")
proto.RegisterType((*OrderSigning)(nil), "orders.OrderSigning")
proto.RegisterType((*PieceHash)(nil), "orders.PieceHash")
proto.RegisterType((*PieceHashSigning)(nil), "orders.PieceHashSigning")
proto.RegisterType((*SettlementRequest)(nil), "orders.SettlementRequest")
proto.RegisterType((*SettlementResponse)(nil), "orders.SettlementResponse")
}
@ -414,56 +654,61 @@ func init() {
func init() { proto.RegisterFile("orders.proto", fileDescriptor_e0f5d4cf0fc9e41b) }
var fileDescriptor_e0f5d4cf0fc9e41b = []byte{
// 775 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x94, 0x4d, 0x6f, 0xf3, 0x44,
0x10, 0xc7, 0xeb, 0xbc, 0x38, 0xc9, 0xe4, 0xcd, 0xd9, 0xa7, 0xaa, 0x42, 0x04, 0x4a, 0x08, 0x97,
0x50, 0xa4, 0x94, 0x06, 0x09, 0xa9, 0x12, 0x42, 0xca, 0x8b, 0x55, 0x4c, 0xab, 0x36, 0xda, 0x24,
0x1c, 0xb8, 0x44, 0x4e, 0xbc, 0xa4, 0x56, 0x1d, 0xdb, 0x78, 0xd7, 0x12, 0xed, 0x15, 0x71, 0xe7,
0x0b, 0x71, 0xe7, 0xc0, 0x27, 0xe0, 0x50, 0xbe, 0x0a, 0xda, 0xf1, 0x5b, 0x0a, 0x45, 0x3c, 0x55,
0x6f, 0x9e, 0x9d, 0xf9, 0xcd, 0xec, 0xec, 0xfc, 0xc7, 0x50, 0xf3, 0x02, 0x8b, 0x05, 0x7c, 0xe8,
0x07, 0x9e, 0xf0, 0x88, 0x1a, 0x59, 0x1d, 0xd8, 0x79, 0x3b, 0x2f, 0x3a, 0xeb, 0x74, 0x77, 0x9e,
0xb7, 0x73, 0xd8, 0x19, 0x5a, 0x9b, 0xf0, 0x87, 0x33, 0x61, 0xef, 0x19, 0x17, 0xe6, 0xde, 0x8f,
0x03, 0xc0, 0xf5, 0x2c, 0x16, 0x7d, 0xf7, 0x7f, 0x56, 0x01, 0x6e, 0x65, 0x8e, 0x6b, 0x7b, 0x6f,
0x0b, 0x72, 0x01, 0x75, 0xce, 0x02, 0xdb, 0x74, 0xd6, 0x6e, 0xb8, 0xdf, 0xb0, 0xa0, 0xad, 0xf4,
0x94, 0x41, 0x6d, 0x72, 0xfc, 0xfb, 0x53, 0xf7, 0xe8, 0xcf, 0xa7, 0x6e, 0x6d, 0x81, 0xce, 0x1b,
0xf4, 0xd1, 0x1a, 0x3f, 0xb0, 0xc8, 0x39, 0xd4, 0xb8, 0x29, 0x98, 0xe3, 0xd8, 0x82, 0xad, 0x6d,
0xab, 0x9d, 0x43, 0xb2, 0x11, 0x93, 0xea, 0x8d, 0x67, 0x31, 0x63, 0x46, 0xab, 0x69, 0x8c, 0x61,
0x91, 0xaf, 0xe0, 0xd8, 0x62, 0x7e, 0xc0, 0xb6, 0xa6, 0x60, 0xd6, 0x3a, 0xf4, 0x1d, 0xdb, 0xbd,
0x97, 0x68, 0x1e, 0x51, 0x38, 0xc0, 0x48, 0x16, 0xb7, 0xc2, 0x30, 0xc3, 0x22, 0x13, 0x68, 0xc5,
0x88, 0x1f, 0x6e, 0x1c, 0x7b, 0xbb, 0xbe, 0x67, 0x0f, 0xed, 0x3a, 0xa2, 0x27, 0x71, 0xd5, 0xc6,
0xdc, 0x66, 0x5b, 0x36, 0x47, 0xf7, 0x15, 0x7b, 0xa0, 0xcd, 0x08, 0x48, 0x0f, 0xc8, 0x97, 0xd0,
0xe4, 0xc2, 0x0b, 0xcc, 0x1d, 0x5b, 0xcb, 0x47, 0x91, 0xc5, 0x0b, 0x2f, 0xde, 0xbb, 0x1e, 0x87,
0xa1, 0x69, 0x91, 0x53, 0x28, 0xfb, 0x32, 0xb5, 0x04, 0x8a, 0x08, 0x34, 0x63, 0xa0, 0x84, 0x25,
0x8d, 0x19, 0x2d, 0x61, 0x80, 0x61, 0x91, 0x63, 0x28, 0x3a, 0xf2, 0x71, 0xdb, 0x6a, 0x4f, 0x19,
0xe4, 0x69, 0x64, 0x90, 0xcf, 0x40, 0x35, 0xb7, 0xc2, 0xf6, 0xdc, 0x76, 0xa9, 0xa7, 0x0c, 0x1a,
0xa3, 0x77, 0xc3, 0x78, 0xb0, 0xc8, 0x8f, 0xd1, 0x45, 0xe3, 0x10, 0x72, 0x0b, 0x5a, 0x54, 0x8e,
0xfd, 0xe4, 0xdb, 0x81, 0x89, 0x58, 0xb9, 0xa7, 0x0c, 0xaa, 0xa3, 0xce, 0x30, 0x9a, 0xf6, 0x30,
0x99, 0xf6, 0x70, 0x99, 0x4c, 0x7b, 0x52, 0x96, 0x57, 0xfa, 0xf5, 0xaf, 0xae, 0x42, 0x9b, 0x48,
0xeb, 0x29, 0x2c, 0x13, 0x62, 0xb9, 0xc3, 0x84, 0x95, 0xd7, 0x24, 0x44, 0xfa, 0x20, 0xe1, 0x15,
0x34, 0xa2, 0x84, 0xdb, 0x80, 0x45, 0xe9, 0x6a, 0xaf, 0x48, 0x57, 0x47, 0x76, 0x1a, 0xa3, 0xe4,
0x0c, 0xde, 0x65, 0x52, 0xe2, 0xf6, 0xce, 0x35, 0x45, 0x18, 0xb0, 0x36, 0xc8, 0x87, 0xa6, 0x24,
0x75, 0x2d, 0x12, 0x0f, 0xf9, 0x1a, 0x5a, 0x19, 0x60, 0x5a, 0x56, 0xc0, 0x38, 0x6f, 0x57, 0xf1,
0x02, 0xad, 0x21, 0xaa, 0x5d, 0xce, 0x6d, 0x1c, 0x39, 0xa8, 0x96, 0xc6, 0xc6, 0x27, 0xfd, 0x5f,
0x14, 0x28, 0xe2, 0x16, 0xbc, 0x65, 0x01, 0x4e, 0x40, 0x35, 0xf7, 0x5e, 0xe8, 0x0a, 0x94, 0x7e,
0x9e, 0xc6, 0x16, 0xf9, 0x14, 0xb4, 0x58, 0xa7, 0x59, 0x2b, 0xa8, 0xf0, 0x44, 0x8e, 0x69, 0x1f,
0xfd, 0x3f, 0x14, 0xa8, 0xe0, 0xfc, 0xbf, 0x31, 0xf9, 0xdd, 0x33, 0x91, 0x29, 0xff, 0x23, 0x32,
0x02, 0x85, 0x3b, 0x93, 0xdf, 0x45, 0x5b, 0x47, 0xf1, 0x9b, 0x7c, 0x04, 0x10, 0xf1, 0xdc, 0x7e,
0x64, 0xa8, 0xeb, 0x3c, 0xad, 0xe0, 0xc9, 0xc2, 0x7e, 0x64, 0x64, 0x02, 0x95, 0xf4, 0xcf, 0x80,
0x22, 0x7e, 0xdf, 0x69, 0x65, 0x18, 0xf9, 0x10, 0x2a, 0xff, 0x6c, 0x2a, 0x3b, 0xe8, 0x6f, 0xa0,
0xb5, 0x60, 0x42, 0x38, 0x6c, 0xcf, 0x5c, 0x41, 0xd9, 0x8f, 0x21, 0xe3, 0x82, 0x0c, 0x92, 0x75,
0x50, 0xb0, 0x24, 0x49, 0x74, 0x9f, 0xfd, 0x85, 0x92, 0x15, 0xf9, 0x04, 0x8a, 0xe8, 0xc3, 0xa6,
0xaa, 0xa3, 0xfa, 0xb3, 0x48, 0x1a, 0xf9, 0xfa, 0xbf, 0x29, 0x40, 0x0e, 0x8b, 0x70, 0xdf, 0x73,
0x39, 0x7b, 0xcb, 0x1c, 0x2f, 0x40, 0xe5, 0xc2, 0x14, 0x21, 0xc7, 0xba, 0x8d, 0xd1, 0xc7, 0x49,
0xdd, 0x7f, 0x97, 0x19, 0x2e, 0x30, 0x90, 0xc6, 0x40, 0xff, 0x1c, 0xd4, 0xe8, 0x84, 0x54, 0xa1,
0x64, 0xdc, 0x7c, 0x37, 0xbe, 0x36, 0x66, 0xda, 0x11, 0xa9, 0x41, 0x79, 0x3c, 0x9d, 0xea, 0xf3,
0xa5, 0x3e, 0xd3, 0x14, 0x69, 0x51, 0xfd, 0x5b, 0x7d, 0x2a, 0xad, 0xdc, 0xe9, 0x0e, 0xaa, 0x07,
0x1b, 0xff, 0x9c, 0x2b, 0x41, 0x7e, 0xbe, 0x5a, 0x6a, 0x8a, 0xfc, 0xb8, 0xd4, 0x97, 0x5a, 0x8e,
0xd4, 0xa1, 0x72, 0xa9, 0x2f, 0xd7, 0xe3, 0xd5, 0xcc, 0x58, 0x6a, 0x79, 0xd2, 0x00, 0x90, 0x26,
0xd5, 0xe7, 0x63, 0x83, 0x6a, 0x05, 0x69, 0xcf, 0x57, 0xa9, 0x5d, 0x24, 0x00, 0xea, 0x4c, 0xbf,
0xd6, 0x97, 0xba, 0xa6, 0x8e, 0x16, 0xa0, 0xe2, 0xc3, 0x71, 0x62, 0x00, 0x64, 0xad, 0x90, 0x0f,
0x5e, 0x6a, 0x0f, 0x47, 0xd5, 0xe9, 0xfc, 0x77, 0xe7, 0xfd, 0xa3, 0x81, 0xf2, 0xb9, 0x32, 0x29,
0x7c, 0x9f, 0xf3, 0x37, 0x1b, 0x15, 0xe5, 0xf2, 0xc5, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xa1,
0x64, 0x18, 0x84, 0x9c, 0x06, 0x00, 0x00,
// 859 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x55, 0xcf, 0x6f, 0xe3, 0x44,
0x14, 0xee, 0x34, 0x89, 0xd3, 0xbc, 0x38, 0xa9, 0x33, 0x5b, 0xad, 0x42, 0x04, 0x6a, 0x09, 0x97,
0xb0, 0x48, 0x29, 0x1b, 0x24, 0xa4, 0x95, 0x50, 0xa5, 0xa4, 0xb1, 0x8a, 0x69, 0xd5, 0x8d, 0x26,
0x29, 0x07, 0x2e, 0x91, 0x13, 0x0f, 0xae, 0xb5, 0x8e, 0x6d, 0x3c, 0x63, 0x89, 0xdd, 0x2b, 0xe2,
0xc6, 0x81, 0x7f, 0x88, 0x3b, 0x07, 0x24, 0xee, 0x1c, 0x96, 0xff, 0x83, 0x13, 0x9a, 0xe7, 0x5f,
0x29, 0x74, 0x05, 0xed, 0x2e, 0x12, 0x70, 0xf3, 0x9b, 0xf7, 0xbe, 0xf7, 0xe6, 0xcd, 0xfb, 0xbe,
0x67, 0xd0, 0xc3, 0xd8, 0xe1, 0xb1, 0x18, 0x46, 0x71, 0x28, 0x43, 0xaa, 0xa5, 0x56, 0x0f, 0xdc,
0xd0, 0x0d, 0xd3, 0xb3, 0xde, 0xa1, 0x1b, 0x86, 0xae, 0xcf, 0x8f, 0xd1, 0x5a, 0x25, 0x5f, 0x1e,
0x4b, 0x6f, 0xc3, 0x85, 0xb4, 0x37, 0x51, 0x16, 0x00, 0x41, 0xe8, 0xf0, 0xf4, 0xbb, 0xff, 0x8d,
0x06, 0xf0, 0x54, 0xe5, 0xb8, 0xf0, 0x36, 0x9e, 0xa4, 0x4f, 0xa0, 0x25, 0x78, 0xec, 0xd9, 0xfe,
0x32, 0x48, 0x36, 0x2b, 0x1e, 0x77, 0xc9, 0x11, 0x19, 0xe8, 0x93, 0x83, 0x1f, 0x5f, 0x1e, 0xee,
0xfc, 0xf2, 0xf2, 0x50, 0x9f, 0xa3, 0xf3, 0x12, 0x7d, 0x4c, 0x17, 0x5b, 0x16, 0x7d, 0x0c, 0xba,
0xb0, 0x25, 0xf7, 0x7d, 0x4f, 0xf2, 0xa5, 0xe7, 0x74, 0x77, 0x11, 0xd9, 0xce, 0x90, 0xda, 0x65,
0xe8, 0x70, 0x6b, 0xca, 0x9a, 0x45, 0x8c, 0xe5, 0xd0, 0x4f, 0xe0, 0xc0, 0xe1, 0x51, 0xcc, 0xd7,
0xb6, 0xe4, 0xce, 0x32, 0x89, 0x7c, 0x2f, 0x78, 0xa6, 0xa0, 0x15, 0x84, 0xc2, 0x16, 0x8c, 0x96,
0x71, 0x57, 0x18, 0x66, 0x39, 0x74, 0x02, 0x9d, 0x0c, 0x12, 0x25, 0x2b, 0xdf, 0x5b, 0x2f, 0x9f,
0xf1, 0xe7, 0xdd, 0x16, 0x42, 0x1f, 0x66, 0x55, 0xdb, 0x33, 0x8f, 0xaf, 0xf9, 0x0c, 0xdd, 0xe7,
0xfc, 0x39, 0xdb, 0x4f, 0x01, 0xc5, 0x01, 0xfd, 0x18, 0xf6, 0x85, 0x0c, 0x63, 0xdb, 0xe5, 0x4b,
0xf5, 0x28, 0xaa, 0x78, 0xf5, 0xd6, 0x7b, 0xb7, 0xb2, 0x30, 0x34, 0x1d, 0xfa, 0x08, 0xf6, 0x22,
0x95, 0x5a, 0x01, 0x6a, 0x08, 0xd8, 0xcf, 0x00, 0x75, 0x2c, 0x69, 0x4d, 0x59, 0x1d, 0x03, 0x2c,
0x87, 0x1e, 0x40, 0xcd, 0x57, 0x8f, 0xdb, 0xd5, 0x8e, 0xc8, 0xa0, 0xc2, 0x52, 0x83, 0x7e, 0x00,
0x9a, 0xbd, 0x96, 0x5e, 0x18, 0x74, 0xeb, 0x47, 0x64, 0xd0, 0x1e, 0x3d, 0x18, 0x66, 0x83, 0x45,
0xfc, 0x18, 0x5d, 0x2c, 0x0b, 0xa1, 0x4f, 0xc1, 0x48, 0xcb, 0xf1, 0xaf, 0x23, 0x2f, 0xb6, 0x11,
0xb6, 0x77, 0x44, 0x06, 0xcd, 0x51, 0x6f, 0x98, 0x4e, 0x7b, 0x98, 0x4f, 0x7b, 0xb8, 0xc8, 0xa7,
0x3d, 0xd9, 0x53, 0x57, 0xfa, 0xfe, 0xd7, 0x43, 0xc2, 0xf6, 0x11, 0x6d, 0x16, 0x60, 0x95, 0x10,
0xcb, 0x6d, 0x27, 0x6c, 0xdc, 0x25, 0x21, 0xa2, 0xb7, 0x12, 0x9e, 0x43, 0x3b, 0x4d, 0xb8, 0x8e,
0x79, 0x9a, 0x4e, 0xbf, 0x43, 0xba, 0x16, 0x62, 0x4f, 0x33, 0x28, 0x3d, 0x86, 0x07, 0x25, 0x95,
0x84, 0xe7, 0x06, 0xb6, 0x4c, 0x62, 0xde, 0x05, 0xf5, 0xd0, 0x8c, 0x16, 0xae, 0x79, 0xee, 0xa1,
0x27, 0xd0, 0x29, 0x01, 0xb6, 0xe3, 0xc4, 0x5c, 0x88, 0x6e, 0x13, 0x2f, 0xd0, 0x19, 0x22, 0xdb,
0xd5, 0xdc, 0xc6, 0xa9, 0x83, 0x19, 0x45, 0x6c, 0x76, 0xd2, 0xff, 0xad, 0x06, 0x9d, 0x52, 0x05,
0x2a, 0xaf, 0x17, 0xb8, 0xff, 0x29, 0x31, 0x9c, 0xbc, 0x5a, 0x0c, 0xf4, 0x7f, 0x24, 0x84, 0xf3,
0x7b, 0x09, 0xa1, 0x7a, 0xbb, 0x08, 0xce, 0xef, 0x25, 0x82, 0xea, 0xed, 0x02, 0x38, 0xbb, 0x87,
0x00, 0xaa, 0xff, 0x0a, 0xf2, 0x7f, 0x4b, 0xa0, 0x86, 0xe4, 0x7f, 0x1d, 0xc2, 0x3f, 0x04, 0xcd,
0xde, 0x84, 0x49, 0x20, 0x91, 0xea, 0x15, 0x96, 0x59, 0xf4, 0x7d, 0x30, 0x32, 0x5e, 0x96, 0xad,
0x20, 0xa3, 0x73, 0x0a, 0x16, 0x7d, 0xf4, 0xbf, 0x23, 0xa0, 0xe3, 0x3d, 0xde, 0x80, 0xfe, 0xde,
0xc0, 0x75, 0x7e, 0x22, 0xd0, 0x40, 0x0a, 0x7e, 0x6a, 0x8b, 0xeb, 0x1b, 0x3c, 0x27, 0x7f, 0xc1,
0x73, 0x0a, 0xd5, 0x6b, 0x5b, 0x5c, 0xa7, 0xa2, 0x67, 0xf8, 0x4d, 0xdf, 0x01, 0x48, 0xf1, 0xc2,
0x7b, 0xc1, 0x51, 0x5a, 0x15, 0xd6, 0xc0, 0x93, 0xb9, 0xf7, 0x82, 0xd3, 0x09, 0x34, 0x8a, 0xbf,
0x34, 0xea, 0xe8, 0xef, 0x6e, 0xce, 0x12, 0x46, 0xdf, 0x86, 0xc6, 0x1f, 0x9b, 0x2a, 0x0f, 0xfa,
0x3f, 0x13, 0x30, 0x8a, 0x76, 0xf2, 0x17, 0xfe, 0x87, 0xbb, 0x3a, 0xb9, 0x5b, 0x57, 0xd5, 0xbb,
0x75, 0xb4, 0x82, 0xce, 0x9c, 0x4b, 0xe9, 0xf3, 0x0d, 0x0f, 0x24, 0xe3, 0x5f, 0x25, 0x5c, 0x48,
0x3a, 0xc8, 0x77, 0x0c, 0xc1, 0x72, 0x34, 0x5f, 0x26, 0xe5, 0x76, 0xcf, 0xf7, 0xce, 0x7b, 0x50,
0x43, 0x1f, 0x36, 0xd4, 0x1c, 0xb5, 0x6e, 0x44, 0xb2, 0xd4, 0xd7, 0xff, 0x81, 0x00, 0xdd, 0x2e,
0x22, 0xa2, 0x30, 0x10, 0xfc, 0x75, 0x98, 0xf9, 0x04, 0x34, 0x21, 0x6d, 0x99, 0x08, 0xac, 0xdb,
0x1e, 0xbd, 0x9b, 0xd7, 0xfd, 0x73, 0x99, 0xe1, 0x1c, 0x03, 0x59, 0x06, 0xe8, 0x3f, 0x06, 0x2d,
0x3d, 0xa1, 0x4d, 0xa8, 0x5b, 0x97, 0x9f, 0x8f, 0x2f, 0xac, 0xa9, 0xb1, 0x43, 0x75, 0xd8, 0x1b,
0x9f, 0x9e, 0x9a, 0xb3, 0x85, 0x39, 0x35, 0x88, 0xb2, 0x98, 0xf9, 0x99, 0x79, 0xaa, 0xac, 0xdd,
0x47, 0x2e, 0x34, 0xb7, 0xd6, 0xe8, 0x4d, 0x5c, 0x1d, 0x2a, 0xb3, 0xab, 0x85, 0x41, 0xd4, 0xc7,
0x99, 0xb9, 0x30, 0x76, 0x69, 0x0b, 0x1a, 0x67, 0xe6, 0x62, 0x39, 0xbe, 0x9a, 0x5a, 0x0b, 0xa3,
0x42, 0xdb, 0x00, 0xca, 0x64, 0xe6, 0x6c, 0x6c, 0x31, 0xa3, 0xaa, 0xec, 0xd9, 0x55, 0x61, 0xd7,
0x28, 0x80, 0x36, 0x35, 0x2f, 0xcc, 0x85, 0x69, 0x68, 0xa3, 0x39, 0x68, 0xf8, 0x70, 0x82, 0x5a,
0x00, 0x65, 0x2b, 0xf4, 0xad, 0xdb, 0xda, 0xc3, 0x51, 0xf5, 0x7a, 0xaf, 0xee, 0xbc, 0xbf, 0x33,
0x20, 0x1f, 0x92, 0x49, 0xf5, 0x8b, 0xdd, 0x68, 0xb5, 0xd2, 0x90, 0x2a, 0x1f, 0xfd, 0x1e, 0x00,
0x00, 0xff, 0xff, 0x87, 0x49, 0x03, 0x47, 0xfa, 0x0a, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.

View File

@ -50,6 +50,41 @@ message OrderLimit {
node.NodeAddress satellite_address = 11;
}
// OrderLimitSigning provides OrderLimit signing serialization
//
// It is never used for sending across the network, it is
// used in signing to ensure that nullable=false fields get handled properly.
// Its purpose is to solidify the format of how we serialize for
// signing, to handle some backwards compatibility considerations.
message OrderLimitSigning {
// unique serial to avoid replay attacks
bytes serial_number = 1 [(gogoproto.customtype) = "SerialNumber", (gogoproto.nullable) = false];
// satellite who issued this order limit allowing orderer to do the specified action
bytes satellite_id = 2 [(gogoproto.customtype) = "NodeID", (gogoproto.nullable) = false];
// uplink who requested or whom behalf the order limit to do an action
bytes deprecated_uplink_id = 3 [(gogoproto.customtype) = "NodeID"];
// public key that will be used to sign orders and piece hash
bytes uplink_public_key = 13 [(gogoproto.customtype) = "PiecePublicKey"];
// storage node who can re claimthe order limit specified by serial
bytes storage_node_id = 4 [(gogoproto.customtype) = "NodeID", (gogoproto.nullable) = false];
// piece which is allowed to be touched
bytes piece_id = 5 [(gogoproto.customtype) = "PieceID", (gogoproto.nullable) = false];
// limit in bytes how much can be changed
int64 limit = 6;
PieceAction action = 7;
google.protobuf.Timestamp piece_expiration = 8 [(gogoproto.stdtime) = true];
google.protobuf.Timestamp order_expiration = 9 [(gogoproto.stdtime) = true];
google.protobuf.Timestamp order_creation = 12 [(gogoproto.stdtime) = true];
bytes satellite_signature = 10;
// satellites aren't necessarily discoverable in kademlia. this allows
// a storage node to find a satellite and handshake with it to get its key.
node.NodeAddress satellite_address = 11;
}
// Order is a one step of fullfilling Amount number of bytes from an OrderLimit with SerialNumber
message Order {
// serial of the order limit that was signed
@ -60,6 +95,21 @@ message Order {
bytes uplink_signature = 3;
}
// OrderSigning provides Order signing format
//
// It is never used for sending across the network, it is
// used in signing to ensure that nullable=false fields get handled properly.
// Its purpose is to solidify the format of how we serialize for
// signing, to handle some backwards compatibility considerations.
message OrderSigning {
// serial of the order limit that was signed
bytes serial_number = 1 [(gogoproto.customtype) = "SerialNumber", (gogoproto.nullable) = false];
// amount to be signed for
int64 amount = 2;
// signature
bytes uplink_signature = 3;
}
message PieceHash {
// piece id
bytes piece_id = 1 [(gogoproto.customtype) = "PieceID", (gogoproto.nullable) = false];
@ -73,6 +123,25 @@ message PieceHash {
bytes signature = 3;
}
// PieceHashSigning provides piece hash signing format.
//
// It is never used for sending across the network, it is
// used in signing to ensure that nullable=false fields get handled properly.
// Its purpose is to solidify the format of how we serialize for
// signing, to handle some backwards compatibility considerations.
message PieceHashSigning {
// piece id
bytes piece_id = 1 [(gogoproto.customtype) = "PieceID", (gogoproto.nullable) = false];
// hash of the piece that was/is uploaded
bytes hash = 2;
// size of uploaded piece
int64 piece_size = 4;
// timestamp when upload occurred
google.protobuf.Timestamp timestamp = 5 [(gogoproto.stdtime) = true];
// signature either satellite or storage node
bytes signature = 3;
}
service Orders {
rpc Settlement(stream SettlementRequest) returns (stream SettlementResponse) {}
}

View File

@ -2860,6 +2860,146 @@
}
]
},
{
"name": "OrderLimitSigning",
"fields": [
{
"id": 1,
"name": "serial_number",
"type": "bytes",
"options": [
{
"name": "(gogoproto.customtype)",
"value": "SerialNumber"
},
{
"name": "(gogoproto.nullable)",
"value": "false"
}
]
},
{
"id": 2,
"name": "satellite_id",
"type": "bytes",
"options": [
{
"name": "(gogoproto.customtype)",
"value": "NodeID"
},
{
"name": "(gogoproto.nullable)",
"value": "false"
}
]
},
{
"id": 3,
"name": "deprecated_uplink_id",
"type": "bytes",
"options": [
{
"name": "(gogoproto.customtype)",
"value": "NodeID"
}
]
},
{
"id": 13,
"name": "uplink_public_key",
"type": "bytes",
"options": [
{
"name": "(gogoproto.customtype)",
"value": "PiecePublicKey"
}
]
},
{
"id": 4,
"name": "storage_node_id",
"type": "bytes",
"options": [
{
"name": "(gogoproto.customtype)",
"value": "NodeID"
},
{
"name": "(gogoproto.nullable)",
"value": "false"
}
]
},
{
"id": 5,
"name": "piece_id",
"type": "bytes",
"options": [
{
"name": "(gogoproto.customtype)",
"value": "PieceID"
},
{
"name": "(gogoproto.nullable)",
"value": "false"
}
]
},
{
"id": 6,
"name": "limit",
"type": "int64"
},
{
"id": 7,
"name": "action",
"type": "PieceAction"
},
{
"id": 8,
"name": "piece_expiration",
"type": "google.protobuf.Timestamp",
"options": [
{
"name": "(gogoproto.stdtime)",
"value": "true"
}
]
},
{
"id": 9,
"name": "order_expiration",
"type": "google.protobuf.Timestamp",
"options": [
{
"name": "(gogoproto.stdtime)",
"value": "true"
}
]
},
{
"id": 12,
"name": "order_creation",
"type": "google.protobuf.Timestamp",
"options": [
{
"name": "(gogoproto.stdtime)",
"value": "true"
}
]
},
{
"id": 10,
"name": "satellite_signature",
"type": "bytes"
},
{
"id": 11,
"name": "satellite_address",
"type": "node.NodeAddress"
}
]
},
{
"name": "Order",
"fields": [
@ -2890,6 +3030,36 @@
}
]
},
{
"name": "OrderSigning",
"fields": [
{
"id": 1,
"name": "serial_number",
"type": "bytes",
"options": [
{
"name": "(gogoproto.customtype)",
"value": "SerialNumber"
},
{
"name": "(gogoproto.nullable)",
"value": "false"
}
]
},
{
"id": 2,
"name": "amount",
"type": "int64"
},
{
"id": 3,
"name": "uplink_signature",
"type": "bytes"
}
]
},
{
"name": "PieceHash",
"fields": [
@ -2940,6 +3110,52 @@
}
]
},
{
"name": "PieceHashSigning",
"fields": [
{
"id": 1,
"name": "piece_id",
"type": "bytes",
"options": [
{
"name": "(gogoproto.customtype)",
"value": "PieceID"
},
{
"name": "(gogoproto.nullable)",
"value": "false"
}
]
},
{
"id": 2,
"name": "hash",
"type": "bytes"
},
{
"id": 4,
"name": "piece_size",
"type": "int64"
},
{
"id": 5,
"name": "timestamp",
"type": "google.protobuf.Timestamp",
"options": [
{
"name": "(gogoproto.stdtime)",
"value": "true"
}
]
},
{
"id": 3,
"name": "signature",
"type": "bytes"
}
]
},
{
"name": "SettlementRequest",
"fields": [