2019-11-08 18:57:51 +00:00
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package gracefulexit
import (
"bytes"
"context"
2019-12-27 11:48:47 +00:00
"storj.io/common/identity"
"storj.io/common/pb"
"storj.io/common/signing"
2019-11-08 18:57:51 +00:00
)
2019-11-21 22:03:16 +00:00
func ( endpoint * Endpoint ) validatePendingTransfer ( ctx context . Context , transfer * PendingTransfer ) error {
if transfer . SatelliteMessage == nil {
2019-11-08 18:57:51 +00:00
return Error . New ( "Satellite message cannot be nil" )
}
2019-11-21 22:03:16 +00:00
if transfer . SatelliteMessage . GetTransferPiece ( ) == nil {
2019-11-08 18:57:51 +00:00
return Error . New ( "Satellite message transfer piece cannot be nil" )
}
2019-11-21 22:03:16 +00:00
if transfer . SatelliteMessage . GetTransferPiece ( ) . GetAddressedOrderLimit ( ) == nil {
2019-11-08 18:57:51 +00:00
return Error . New ( "Addressed order limit on transfer piece cannot be nil" )
}
2019-11-21 22:03:16 +00:00
if transfer . SatelliteMessage . GetTransferPiece ( ) . GetAddressedOrderLimit ( ) . GetLimit ( ) == nil {
2019-11-08 18:57:51 +00:00
return Error . New ( "Addressed order limit on transfer piece cannot be nil" )
}
2021-09-05 22:29:22 +01:00
if transfer . StreamID . IsZero ( ) {
return Error . New ( "StreamID cannot be zero" )
2019-11-08 18:57:51 +00:00
}
2020-12-16 16:47:31 +00:00
if transfer . OriginalRootPieceID . IsZero ( ) {
return Error . New ( "could not get original root piece ID from transfer item" )
2019-11-08 18:57:51 +00:00
}
return nil
}
2019-11-21 22:03:16 +00:00
func ( endpoint * Endpoint ) verifyPieceTransferred ( ctx context . Context , message * pb . StorageNodeMessage_Succeeded , transfer * PendingTransfer , receivingNodePeerID * identity . PeerIdentity ) error {
2019-11-08 18:57:51 +00:00
originalOrderLimit := message . Succeeded . GetOriginalOrderLimit ( )
if originalOrderLimit == nil {
return ErrInvalidArgument . New ( "Original order limit cannot be nil" )
}
originalPieceHash := message . Succeeded . GetOriginalPieceHash ( )
if originalPieceHash == nil {
return ErrInvalidArgument . New ( "Original piece hash cannot be nil" )
}
replacementPieceHash := message . Succeeded . GetReplacementPieceHash ( )
if replacementPieceHash == nil {
return ErrInvalidArgument . New ( "Replacement piece hash cannot be nil" )
}
// verify that the original piece hash and replacement piece hash match
if ! bytes . Equal ( originalPieceHash . Hash , replacementPieceHash . Hash ) {
return ErrInvalidArgument . New ( "Piece hashes for transferred piece don't match" )
}
// verify that the satellite signed the original order limit
err := signing . VerifyOrderLimitSignature ( ctx , endpoint . signer , originalOrderLimit )
if err != nil {
2020-05-26 23:25:20 +01:00
return ErrInvalidArgument . New ( "Could not validate signature from satellite on claimed original order limit: %v" , err )
2019-11-08 18:57:51 +00:00
}
// verify that the public key on the order limit signed the original piece hash
err = signing . VerifyUplinkPieceHashSignature ( ctx , originalOrderLimit . UplinkPublicKey , originalPieceHash )
if err != nil {
2020-05-26 23:25:20 +01:00
return ErrInvalidArgument . New ( "Could not validate signature from original order limit's public key on original piece hash: %v" , err )
2019-11-08 18:57:51 +00:00
}
if originalOrderLimit . PieceId != message . Succeeded . OriginalPieceId {
2020-05-26 23:25:20 +01:00
return ErrInvalidArgument . New ( "Original piece ID in piece-transfer success message does not match piece ID in original order limit" )
2019-11-08 18:57:51 +00:00
}
2019-11-21 22:03:16 +00:00
receivingNodeID := transfer . SatelliteMessage . GetTransferPiece ( ) . GetAddressedOrderLimit ( ) . GetLimit ( ) . StorageNodeId
2020-12-16 16:47:31 +00:00
calculatedNewPieceID := transfer . OriginalRootPieceID . Derive ( receivingNodeID , int32 ( transfer . PieceNum ) )
2019-11-08 18:57:51 +00:00
if calculatedNewPieceID != replacementPieceHash . PieceId {
2020-05-26 23:25:20 +01:00
return ErrInvalidArgument . New ( "Replacement piece ID does not match derived piece ID for receivingNodeID %s, PieceNum %d: %q != %q" , receivingNodeID . String ( ) , transfer . PieceNum , calculatedNewPieceID . String ( ) , replacementPieceHash . PieceId . String ( ) )
2019-11-08 18:57:51 +00:00
}
2020-05-26 23:25:20 +01:00
signer := signing . SigneeFromPeerIdentity ( receivingNodePeerID )
2019-11-08 18:57:51 +00:00
// verify that the new node signed the replacement piece hash
2020-05-26 23:25:20 +01:00
err = signing . VerifyPieceHashSignature ( ctx , signer , replacementPieceHash )
2019-11-08 18:57:51 +00:00
if err != nil {
2020-05-26 23:25:20 +01:00
return ErrInvalidArgument . New ( "Could not validate signature from receiving node on replacement piece hash: %v" , err )
2019-11-08 18:57:51 +00:00
}
return nil
}