github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/fvm/evm/types/proof.go (about)

     1  package types
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/onflow/cadence"
     7  	"github.com/onflow/cadence/runtime/common"
     8  	"github.com/onflow/cadence/runtime/sema"
     9  	cadenceRLP "github.com/onflow/cadence/runtime/stdlib/rlp"
    10  	"github.com/onflow/go-ethereum/rlp"
    11  
    12  	"github.com/onflow/flow-go/model/flow"
    13  )
    14  
    15  type FlowAddress flow.Address
    16  
    17  var FlowAddressCadenceType = cadence.AddressType
    18  var FlowAddressSemaType = sema.TheAddressType
    19  
    20  func (addr FlowAddress) ToCadenceValue() cadence.Address {
    21  	return cadence.Address(addr)
    22  }
    23  
    24  type PublicPath string
    25  
    26  var PublicPathCadenceType = cadence.PathType
    27  var PublicPathSemaType = sema.PathType
    28  
    29  func (p PublicPath) ToCadenceValue() cadence.Path {
    30  	return cadence.Path{
    31  		Domain:     common.PathDomainPublic,
    32  		Identifier: string(p),
    33  	}
    34  }
    35  
    36  type SignedData []byte
    37  
    38  var SignedDataCadenceType = cadence.NewVariableSizedArrayType(cadence.UInt8Type)
    39  var SignedDataSemaType = sema.ByteArrayType
    40  
    41  func (sd SignedData) ToCadenceValue() cadence.Array {
    42  	values := make([]cadence.Value, len(sd))
    43  	for i, v := range sd {
    44  		values[i] = cadence.NewUInt8(v)
    45  	}
    46  	return cadence.NewArray(values).WithType(SignedDataCadenceType)
    47  }
    48  
    49  type KeyIndices []uint64
    50  
    51  var KeyIndicesCadenceType = cadence.NewVariableSizedArrayType(cadence.UInt64Type)
    52  var KeyIndicesSemaType = &sema.VariableSizedType{Type: sema.UInt64Type}
    53  
    54  func (ki KeyIndices) ToCadenceValue() cadence.Array {
    55  	values := make([]cadence.Value, len(ki))
    56  	for i, v := range ki {
    57  		values[i] = cadence.NewUInt64(v)
    58  	}
    59  	return cadence.NewArray(values).WithType(KeyIndicesCadenceType)
    60  }
    61  
    62  func (ki KeyIndices) Count() int {
    63  	return len(ki)
    64  }
    65  
    66  type Signature []byte
    67  
    68  var SignatureCadenceType = cadence.NewVariableSizedArrayType(cadence.UInt8Type)
    69  
    70  func (s Signature) ToCadenceValue() cadence.Array {
    71  	values := make([]cadence.Value, len(s))
    72  	for i, v := range s {
    73  		values[i] = cadence.NewUInt8(v)
    74  	}
    75  	return cadence.NewArray(values).WithType(SignatureCadenceType)
    76  }
    77  
    78  type Signatures []Signature
    79  
    80  var SignaturesCadenceType = cadence.NewVariableSizedArrayType(SignatureCadenceType)
    81  var SignaturesSemaType = sema.ByteArrayArrayType
    82  
    83  func (ss Signatures) ToCadenceValue() cadence.Array {
    84  	values := make([]cadence.Value, len(ss))
    85  	for i, s := range ss {
    86  		values[i] = s.ToCadenceValue()
    87  	}
    88  	return cadence.NewArray(values).WithType(SignaturesCadenceType)
    89  }
    90  
    91  func (ss Signatures) Count() int {
    92  	return len(ss)
    93  }
    94  
    95  // COAOwnershipProofInContext contains all the data
    96  // needed to verify a COAOwnership proof.
    97  // The proof is verified by checking the signatures over the
    98  // input signed data (SignedData), then loading the resource
    99  // capability from the provided path in the proof, and
   100  // at last checking if the EVMAddress of the resource matches
   101  // the provided one.
   102  type COAOwnershipProofInContext struct {
   103  	COAOwnershipProof
   104  	SignedData SignedData
   105  	EVMAddress Address
   106  }
   107  
   108  func NewCOAOwnershipProofInContext(sd []byte, addr Address, encodedProof []byte) (*COAOwnershipProofInContext, error) {
   109  	proof, err := COAOwnershipProofFromEncoded(encodedProof)
   110  	if err != nil {
   111  		return nil, err
   112  	}
   113  	return &COAOwnershipProofInContext{
   114  		COAOwnershipProof: *proof,
   115  		SignedData:        sd,
   116  		EVMAddress:        addr,
   117  	}, nil
   118  }
   119  
   120  func (proof *COAOwnershipProofInContext) ToCadenceValues() []cadence.Value {
   121  	return []cadence.Value{
   122  		proof.Address.ToCadenceValue(),
   123  		proof.CapabilityPath.ToCadenceValue(),
   124  		proof.SignedData.ToCadenceValue(),
   125  		proof.KeyIndices.ToCadenceValue(),
   126  		proof.Signatures.ToCadenceValue(),
   127  		proof.EVMAddress.ToCadenceValue(),
   128  	}
   129  }
   130  
   131  // COAOwnershipProof is a proof that a flow account
   132  // controls a COA resource. To do so, the flow
   133  // account (Address is address of this account)
   134  // provides signatures (with proper total weights) over an arbitary data input
   135  // set by proof requester. KeyIndicies captures,
   136  // which account keys has been used for signatures.
   137  // Beside signatures, it provides the CapabilityPath
   138  // where the resource EVMAddress capability is stored.
   139  type COAOwnershipProof struct {
   140  	KeyIndices     KeyIndices
   141  	Address        FlowAddress
   142  	CapabilityPath PublicPath
   143  	Signatures     Signatures
   144  }
   145  
   146  func (p *COAOwnershipProof) Encode() ([]byte, error) {
   147  	return rlp.EncodeToBytes(p)
   148  }
   149  
   150  func COAOwnershipProofSignatureCountFromEncoded(data []byte) (int, error) {
   151  	// first break into proof encoded items
   152  	encodedItems, _, err := cadenceRLP.DecodeList(data, 0)
   153  	if err != nil {
   154  		return 0, err
   155  	}
   156  	// first encoded item is KeyIndicies
   157  	// so reading number of elements in the key indicies
   158  	// should return the count without the need to fully decode
   159  	KeyIndices, _, err := cadenceRLP.DecodeList(encodedItems[0], 0)
   160  	return len(KeyIndices), err
   161  }
   162  
   163  func COAOwnershipProofFromEncoded(data []byte) (*COAOwnershipProof, error) {
   164  	if len(data) == 0 {
   165  		return nil, fmt.Errorf("empty proof")
   166  	}
   167  	p := &COAOwnershipProof{}
   168  	return p, rlp.DecodeBytes(data, p)
   169  }