github.com/baptiste-b-pegasys/quorum/v22@v22.4.2/core/state/account_extra_data.go (about)

     1  // Copyright 2014 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package state
    18  
    19  import (
    20  	"fmt"
    21  	"io"
    22  
    23  	"github.com/ethereum/go-ethereum/common"
    24  	"github.com/ethereum/go-ethereum/private/engine"
    25  	"github.com/ethereum/go-ethereum/rlp"
    26  )
    27  
    28  // Quorum
    29  // AccountExtraData is to contain extra data that supplements existing Account data.
    30  // It is also maintained in a trie to support rollback.
    31  // Note:
    32  // - update copy() method
    33  // - update DecodeRLP and EncodeRLP when adding new field
    34  type AccountExtraData struct {
    35  	// for privacy enhancements
    36  	PrivacyMetadata *PrivacyMetadata
    37  	// list of public keys managed by the corresponding Tessera.
    38  	// This is for multitenancy
    39  	ManagedParties []string
    40  }
    41  
    42  func (qmd *AccountExtraData) DecodeRLP(stream *rlp.Stream) error {
    43  	var dataRLP struct {
    44  		// from state.PrivacyMetadata, this is required to support
    45  		// backward compatibility with RLP-encoded state.PrivacyMetadata.
    46  		// Refer to rlp/doc.go for decoding rules.
    47  		CreationTxHash *common.EncryptedPayloadHash `rlp:"nil"`
    48  		// from state.PrivacyMetadata, this is required to support
    49  		// backward compatibility with RLP-encoded state.PrivacyMetadata.
    50  		// Refer to rlp/doc.go for decoding rules.
    51  		PrivacyFlag *engine.PrivacyFlagType `rlp:"nil"`
    52  
    53  		Rest []rlp.RawValue `rlp:"tail"` // to maintain forward compatibility
    54  	}
    55  	if err := stream.Decode(&dataRLP); err != nil {
    56  		return err
    57  	}
    58  	if dataRLP.CreationTxHash != nil && dataRLP.PrivacyFlag != nil {
    59  		qmd.PrivacyMetadata = &PrivacyMetadata{
    60  			CreationTxHash: *dataRLP.CreationTxHash,
    61  			PrivacyFlag:    *dataRLP.PrivacyFlag,
    62  		}
    63  	}
    64  	if len(dataRLP.Rest) > 0 {
    65  		var managedParties []string
    66  		if err := rlp.DecodeBytes(dataRLP.Rest[0], &managedParties); err != nil {
    67  			return fmt.Errorf("fail to decode managedParties with error %v", err)
    68  		}
    69  		// As RLP encodes empty slice or nil slice as an empty string (192)
    70  		// we won't be able to determine when decoding. So we use pragmatic approach
    71  		// to default to nil value. Downstream usage would deal with it easier.
    72  		if len(managedParties) == 0 {
    73  			qmd.ManagedParties = nil
    74  		} else {
    75  			qmd.ManagedParties = managedParties
    76  		}
    77  	}
    78  	return nil
    79  }
    80  
    81  func (qmd *AccountExtraData) EncodeRLP(writer io.Writer) error {
    82  	var (
    83  		hash *common.EncryptedPayloadHash
    84  		flag *engine.PrivacyFlagType
    85  	)
    86  	if qmd.PrivacyMetadata != nil {
    87  		hash = &qmd.PrivacyMetadata.CreationTxHash
    88  		flag = &qmd.PrivacyMetadata.PrivacyFlag
    89  	}
    90  	return rlp.Encode(writer, struct {
    91  		CreationTxHash *common.EncryptedPayloadHash `rlp:"nil"`
    92  		PrivacyFlag    *engine.PrivacyFlagType      `rlp:"nil"`
    93  		ManagedParties []string
    94  	}{
    95  		CreationTxHash: hash,
    96  		PrivacyFlag:    flag,
    97  		ManagedParties: qmd.ManagedParties,
    98  	})
    99  }
   100  
   101  func (qmd *AccountExtraData) copy() *AccountExtraData {
   102  	if qmd == nil {
   103  		return nil
   104  	}
   105  	var copyPM *PrivacyMetadata
   106  	if qmd.PrivacyMetadata != nil {
   107  		copyPM = &PrivacyMetadata{
   108  			CreationTxHash: qmd.PrivacyMetadata.CreationTxHash,
   109  			PrivacyFlag:    qmd.PrivacyMetadata.PrivacyFlag,
   110  		}
   111  	}
   112  	copyManagedParties := make([]string, len(qmd.ManagedParties))
   113  	copy(copyManagedParties, qmd.ManagedParties)
   114  	return &AccountExtraData{
   115  		PrivacyMetadata: copyPM,
   116  		ManagedParties:  copyManagedParties,
   117  	}
   118  }
   119  
   120  // attached to every private contract account
   121  type PrivacyMetadata struct {
   122  	CreationTxHash common.EncryptedPayloadHash `json:"creationTxHash"`
   123  	PrivacyFlag    engine.PrivacyFlagType      `json:"privacyFlag"`
   124  }
   125  
   126  // Quorum
   127  // privacyMetadataRLP struct is to make sure
   128  // field order is preserved regardless changes in the PrivacyMetadata and its internal
   129  //
   130  // Edit this struct with care to make sure forward and backward compatibility
   131  type privacyMetadataRLP struct {
   132  	CreationTxHash common.EncryptedPayloadHash
   133  	PrivacyFlag    engine.PrivacyFlagType
   134  
   135  	Rest []rlp.RawValue `rlp:"tail"` // to maintain forward compatibility
   136  }
   137  
   138  func (p *PrivacyMetadata) DecodeRLP(stream *rlp.Stream) error {
   139  	var dataRLP privacyMetadataRLP
   140  	if err := stream.Decode(&dataRLP); err != nil {
   141  		return err
   142  	}
   143  	p.CreationTxHash = dataRLP.CreationTxHash
   144  	p.PrivacyFlag = dataRLP.PrivacyFlag
   145  	return nil
   146  }
   147  
   148  func (p *PrivacyMetadata) EncodeRLP(writer io.Writer) error {
   149  	return rlp.Encode(writer, privacyMetadataRLP{
   150  		CreationTxHash: p.CreationTxHash,
   151  		PrivacyFlag:    p.PrivacyFlag,
   152  	})
   153  }
   154  
   155  func NewStatePrivacyMetadata(creationTxHash common.EncryptedPayloadHash, privacyFlag engine.PrivacyFlagType) *PrivacyMetadata {
   156  	return &PrivacyMetadata{
   157  		CreationTxHash: creationTxHash,
   158  		PrivacyFlag:    privacyFlag,
   159  	}
   160  }