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 }