Skip to content

Understanding Attestation Response#

A successful Notarize call will return an Attestation Response, which we will break down here.

Example weather attestation response formatted as JSON
[
  {
    "enclaveUrl": "omitted",
    "attestationReport": "AQAAAAIAAAD4EQAAAAAAAAMAAgAAAAAACgAPAJOacjP3nEyplAoNs5V/BgfL/8e2niibMd2lSZMZV5SwAAAAABUVCwf/gA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAABwAAAAAAAADlRzp8bNOrKrQCu5A02t2vmCHsO+a5/Du11uzLzT6ekwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9H4s7YPOeZFug8XZRRRlc+Z7Vfit98IfkZsrDpb+DxsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA67Cx768zCyjHKiKvJeqqxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQQAADoYWnc79tpibdmxv3XYL8oyY/hN5Vfi/fUFju+xafJcZYBU27Knf13c42ssayhP192yFq9tN0+0mmvKZNcLnTXxG76NsaVfFF6tBYAT+KjfyEnIS69AbRGJESM9r6nUgqsO4eILvEDZ/bdTRLbhdOMicQRRVqTKTSok3FoaemN3xUVCwf/gA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUAAAAAAAAABwAAAAAAAACWs0emTloEXic2nCbm3NpR/XyFDps6OnnnGPQyYd7h5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjE9XddeWUD6WE393xoqCmgBWrI3tcBQLCBsJRJDFe/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnx88oavq2dYufVH0BxRHJ6/MWhYcaUqrAcukxayLqRcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABrq0aRpapY8nVpydMzFfU6mrRkzmz5SY2bTdXyiIx9jY/LeFBJyOTyyQXT1Nd2K/RXGEjOOywPwXbAdSv/Lvb8gAAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fBQDcDQAALS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVqakNDQkRPZ0F3SUJBZ0lVUWp0VzA4OVBCdjgzTkM1emo4VHMwODY4R0FJd0NnWUlLb1pJemowRUF3SXcKY1RFak1DRUdBMVVFQXd3YVNXNTBaV3dnVTBkWUlGQkRTeUJRY205alpYTnpiM0lnUTBFeEdqQVlCZ05WQkFvTQpFVWx1ZEdWc0lFTnZjbkJ2Y21GMGFXOXVNUlF3RWdZRFZRUUhEQXRUWVc1MFlTQkRiR0Z5WVRFTE1Ba0dBMVVFCkNBd0NRMEV4Q3pBSkJnTlZCQVlUQWxWVE1CNFhEVEl6TVRJd056RTJNemN5TWxvWERUTXdNVEl3TnpFMk16Y3kKTWxvd2NERWlNQ0FHQTFVRUF3d1pTVzUwWld3Z1UwZFlJRkJEU3lCRFpYSjBhV1pwWTJGMFpURWFNQmdHQTFVRQpDZ3dSU1c1MFpXd2dRMjl5Y0c5eVlYUnBiMjR4RkRBU0JnTlZCQWNNQzFOaGJuUmhJRU5zWVhKaE1Rc3dDUVlEClZRUUlEQUpEUVRFTE1Ba0dBMVVFQmhNQ1ZWTXdXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CQndOQ0FBUnUKQ2p6bHFrU0M0M3pqUnlVZlRKWk8va2ZraXdhNURudkxERGl1YXNxVjRvUUJWYitHQlZNREppZEE0UVI0QXdhZQpGczlVdGRLanRKTTlLMDVvUW5lb280SUNxRENDQXFRd0h3WURWUjBqQkJnd0ZvQVUwT2lxMm5YWCtTNUpGNWc4CmV4UmwwTlh5V1Uwd2JBWURWUjBmQkdVd1l6QmhvRitnWFlaYmFIUjBjSE02THk5aGNHa3VkSEoxYzNSbFpITmwKY25acFkyVnpMbWx1ZEdWc0xtTnZiUzl6WjNndlkyVnlkR2xtYVdOaGRHbHZiaTkyTkM5d1kydGpjbXcvWTJFOQpjSEp2WTJWemMyOXlKbVZ1WTI5a2FXNW5QV1JsY2pBZEJnTlZIUTRFRmdRVXlpWFNzZzJrYWpoME1iU3FBbGlyCjBGaWxLMUl3RGdZRFZSMFBBUUgvQkFRREFnYkFNQXdHQTFVZEV3RUIvd1FDTUFBd2dnSFVCZ2txaGtpRytFMEIKRFFFRWdnSEZNSUlCd1RBZUJnb3Foa2lHK0UwQkRRRUJCQkF4Ukl0SDA0MzRNMDFVcWI4OXB5eHBNSUlCWkFZSwpLb1pJaHZoTkFRMEJBakNDQVZRd0VBWUxLb1pJaHZoTkFRMEJBZ0VDQVJVd0VBWUxLb1pJaHZoTkFRMEJBZ0lDCkFSVXdFQVlMS29aSWh2aE5BUTBCQWdNQ0FRSXdFQVlMS29aSWh2aE5BUTBCQWdRQ0FRUXdFQVlMS29aSWh2aE4KQVEwQkFnVUNBUUV3RVFZTEtvWklodmhOQVEwQkFnWUNBZ0NBTUJBR0N5cUdTSWI0VFFFTkFRSUhBZ0VPTUJBRwpDeXFHU0liNFRRRU5BUUlJQWdFQU1CQUdDeXFHU0liNFRRRU5BUUlKQWdFQU1CQUdDeXFHU0liNFRRRU5BUUlLCkFnRUFNQkFHQ3lxR1NJYjRUUUVOQVFJTEFnRUFNQkFHQ3lxR1NJYjRUUUVOQVFJTUFnRUFNQkFHQ3lxR1NJYjQKVFFFTkFRSU5BZ0VBTUJBR0N5cUdTSWI0VFFFTkFRSU9BZ0VBTUJBR0N5cUdTSWI0VFFFTkFRSVBBZ0VBTUJBRwpDeXFHU0liNFRRRU5BUUlRQWdFQU1CQUdDeXFHU0liNFRRRU5BUUlSQWdFTk1COEdDeXFHU0liNFRRRU5BUUlTCkJCQVZGUUlFQVlBT0FBQUFBQUFBQUFBQU1CQUdDaXFHU0liNFRRRU5BUU1FQWdBQU1CUUdDaXFHU0liNFRRRU4KQVFRRUJnQ1FidFVBQURBUEJnb3Foa2lHK0UwQkRRRUZDZ0VBTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDSVFDNgoxaXhnZ1lDd0ZEcjl6cmMrMUF3M3dGanc2THZtbHdJc0E1Q0JxUzlqQndJaEFQVzZ0RUJqcVZjanRzalYxWXIxCkt2NHE4VjNBLzNTU2lLaHJFVEtSTFUyaQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQpNSUlDbURDQ0FqNmdBd0lCQWdJVkFORG9xdHAxMS9rdVNSZVlQSHNVWmREVjhsbE5NQW9HQ0NxR1NNNDlCQU1DCk1HZ3hHakFZQmdOVkJBTU1FVWx1ZEdWc0lGTkhXQ0JTYjI5MElFTkJNUm93R0FZRFZRUUtEQkZKYm5SbGJDQkQKYjNKd2IzSmhkR2x2YmpFVU1CSUdBMVVFQnd3TFUyRnVkR0VnUTJ4aGNtRXhDekFKQmdOVkJBZ01Ba05CTVFzdwpDUVlEVlFRR0V3SlZVekFlRncweE9EQTFNakV4TURVd01UQmFGdzB6TXpBMU1qRXhNRFV3TVRCYU1IRXhJekFoCkJnTlZCQU1NR2tsdWRHVnNJRk5IV0NCUVEwc2dVSEp2WTJWemMyOXlJRU5CTVJvd0dBWURWUVFLREJGSmJuUmwKYkNCRGIzSndiM0poZEdsdmJqRVVNQklHQTFVRUJ3d0xVMkZ1ZEdFZ1EyeGhjbUV4Q3pBSkJnTlZCQWdNQWtOQgpNUXN3Q1FZRFZRUUdFd0pWVXpCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkw5cStOTXAySU9nCnRkbDFiay91V1o1K1RHUW04YUNpOHo3OGZzK2ZLQ1EzZCt1RHpYblZUQVQyWmhEQ2lmeUl1Snd2TjN3TkJwOWkKSEJTU01KTUpyQk9qZ2Jzd2diZ3dId1lEVlIwakJCZ3dGb0FVSW1VTTFscWROSW56ZzdTVlVyOVFHemtuQnF3dwpVZ1lEVlIwZkJFc3dTVEJIb0VXZ1E0WkJhSFIwY0hNNkx5OWpaWEowYVdacFkyRjBaWE11ZEhKMWMzUmxaSE5sCmNuWnBZMlZ6TG1sdWRHVnNMbU52YlM5SmJuUmxiRk5IV0ZKdmIzUkRRUzVrWlhJd0hRWURWUjBPQkJZRUZORG8KcXRwMTEva3VTUmVZUEhzVVpkRFY4bGxOTUE0R0ExVWREd0VCL3dRRUF3SUJCakFTQmdOVkhSTUJBZjhFQ0RBRwpBUUgvQWdFQU1Bb0dDQ3FHU000OUJBTUNBMGdBTUVVQ0lRQ0pnVGJ0VnFPeVoxbTNqcWlBWE02UVlhNnI1c1dTCjR5L0c3eTh1SUpHeGR3SWdScVB2QlNLenpRYWdCTFFxNXM1QTcwcGRvaWFSSjh6LzB1RHo0TmdWOTFrPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQpNSUlDanpDQ0FqU2dBd0lCQWdJVUltVU0xbHFkTkluemc3U1ZVcjlRR3prbkJxd3dDZ1lJS29aSXpqMEVBd0l3CmFERWFNQmdHQTFVRUF3d1JTVzUwWld3Z1UwZFlJRkp2YjNRZ1EwRXhHakFZQmdOVkJBb01FVWx1ZEdWc0lFTnYKY25CdmNtRjBhVzl1TVJRd0VnWURWUVFIREF0VFlXNTBZU0JEYkdGeVlURUxNQWtHQTFVRUNBd0NRMEV4Q3pBSgpCZ05WQkFZVEFsVlRNQjRYRFRFNE1EVXlNVEV3TkRVeE1Gb1hEVFE1TVRJek1USXpOVGsxT1Zvd2FERWFNQmdHCkExVUVBd3dSU1c1MFpXd2dVMGRZSUZKdmIzUWdRMEV4R2pBWUJnTlZCQW9NRVVsdWRHVnNJRU52Y25CdmNtRjAKYVc5dU1SUXdFZ1lEVlFRSERBdFRZVzUwWVNCRGJHRnlZVEVMTUFrR0ExVUVDQXdDUTBFeEN6QUpCZ05WQkFZVApBbFZUTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFQzZuRXdNRElZWk9qL2lQV3NDemFFS2k3CjFPaU9TTFJGaFdHamJuQlZKZlZua1k0dTNJamtEWVlMME14TzRtcXN5WWpsQmFsVFZZeEZQMnNKQks1emxLT0IKdXpDQnVEQWZCZ05WSFNNRUdEQVdnQlFpWlF6V1dwMDBpZk9EdEpWU3YxQWJPU2NHckRCU0JnTlZIUjhFU3pCSgpNRWVnUmFCRGhrRm9kSFJ3Y3pvdkwyTmxjblJwWm1sallYUmxjeTUwY25WemRHVmtjMlZ5ZG1salpYTXVhVzUwClpXd3VZMjl0TDBsdWRHVnNVMGRZVW05dmRFTkJMbVJsY2pBZEJnTlZIUTRFRmdRVUltVU0xbHFkTkluemc3U1YKVXI5UUd6a25CcXd3RGdZRFZSMFBBUUgvQkFRREFnRUdNQklHQTFVZEV3RUIvd1FJTUFZQkFmOENBUUV3Q2dZSQpLb1pJemowRUF3SURTUUF3UmdJaEFPVy81UWtSK1M5Q2lTRGNOb293THVQUkxzV0dmL1lpN0dTWDk0Qmd3VHdnCkFpRUE0SjBsckhvTXMrWG81by9zWDZPOVFXeEhSQXZaVUdPZFJRN2N2cVJYYXFJPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCgA=",
    "reportType": "sgx",
    "attestationData": "9.90",
    "responseBody": "{\"latitude\":42.917397,\"longitude\":-74.37686,\"generationtime_ms\":0.16999244689941406,\"utc_offset_seconds\":0,\"timezone\":\"GMT\",\"timezone_abbreviation\":\"GMT\",\"elevation\":117.0,\"daily_units\":{\"time\":\"iso8601\",\"rain_sum\":\"mm\"},\"daily\":{\"time\":[\"2024-02-28\"],\"rain_sum\":[9.90]}}",
    "responseStatusCode": 200,
    "timestamp": 1709730029,
    "oracleData": {
      "signature": "sign1x2kx7gssjd9a5davpazug4mj5k82634q5n4cha03akp734cwgsqwhrm4rfxpd4h6fpkz253v9yqp00s9fqpgpyfafcdjk08sy4fhvpps9fyug6x7nlr2ws0209uhsps4dv9g6998qnhc2g6f6vw4pug7qmefrdv65eg2d6v2lq2r5ezldy9rfgw2xrauwzfms3d5r793ldzsyjag5g2",
      "userData": "{  c0: {    f0: 83078176003060725451284209119789060u128,    f1: 4194512u128,    f2: 990u128,    f3: 1709730029u128,    f4: 200u128,    f5: 146741781957618190040822128409835696737u128,    f6: 152036601506766190083586533414400257325u128,    f7: 69438642371722949660980644949730617443u128,    f8: 133532659421421713743881801343056817714u128,    f9: 152038006197340572103123007711229066597u128,    f10: 66696071085301770748652136257525407604u128,    f11: 60086277185945482657482972579083134520u128,    f12: 146762247151254361341361560418480108080u128,    f13: 1836413791u128,    f14: 121200813359967904192723595955179970916u128,    f15: 23856u128,    f16: 0u128,    f17: 5522759u128,    f18: 36893488147419103234u128,    f19: 221360928884514619396u128,    f20: 13055389343712134841237569546u128,    f21: 13856407623565317u128,    f22: 156035770564570580066107481452631621659u128,    f23: 3900269670161044694030315513202u128,    f24: 162743726813863731210145153184655802480u128,    f25: 101188681738744639914108759155086748777u128,    f26: 149456393680743922584091041160660086377u128,    f27: 42816717959947032433996830433837802860u128,    f28: 132119436183189587630719372684727700264u128,    f29: 64042929165508395635299690384626118507u128,    f30: 61431102749981217983499061483759611950u128,    f31: 13875u128  },  c1: {    f0: 55340232221128654848u128,    f1: 0u128,    f2: 0u128,    f3: 0u128,    f4: 0u128,    f5: 0u128,    f6: 0u128,    f7: 0u128,    f8: 0u128,    f9: 0u128,    f10: 0u128,    f11: 0u128,    f12: 0u128,    f13: 0u128,    f14: 0u128,    f15: 0u128,    f16: 0u128,    f17: 0u128,    f18: 0u128,    f19: 0u128,    f20: 0u128,    f21: 0u128,    f22: 0u128,    f23: 0u128,    f24: 0u128,    f25: 0u128,    f26: 0u128,    f27: 0u128,    f28: 0u128,    f29: 0u128,    f30: 0u128,    f31: 0u128  },  c2: {    f0: 0u128,    f1: 0u128,    f2: 0u128,    f3: 0u128,    f4: 0u128,    f5: 0u128,    f6: 0u128,    f7: 0u128,    f8: 0u128,    f9: 0u128,    f10: 0u128,    f11: 0u128,    f12: 0u128,    f13: 0u128,    f14: 0u128,    f15: 0u128,    f16: 0u128,    f17: 0u128,    f18: 0u128,    f19: 0u128,    f20: 0u128,    f21: 0u128,    f22: 0u128,    f23: 0u128,    f24: 0u128,    f25: 0u128,    f26: 0u128,    f27: 0u128,    f28: 0u128,    f29: 0u128,    f30: 0u128,    f31: 0u128  },  c3: {    f0: 0u128,    f1: 0u128,    f2: 0u128,    f3: 0u128,    f4: 0u128,    f5: 0u128,    f6: 0u128,    f7: 0u128,    f8: 0u128,    f9: 0u128,    f10: 0u128,    f11: 0u128,    f12: 0u128,    f13: 0u128,    f14: 0u128,    f15: 0u128,    f16: 0u128,    f17: 0u128,    f18: 0u128,    f19: 0u128,    f20: 0u128,    f21: 0u128,    f22: 0u128,    f23: 0u128,    f24: 0u128,    f25: 0u128,    f26: 0u128,    f27: 0u128,    f28: 0u128,    f29: 0u128,    f30: 0u128,    f31: 0u128  },  c4: {    f0: 0u128,    f1: 0u128,    f2: 0u128,    f3: 0u128,    f4: 0u128,    f5: 0u128,    f6: 0u128,    f7: 0u128,    f8: 0u128,    f9: 0u128,    f10: 0u128,    f11: 0u128,    f12: 0u128,    f13: 0u128,    f14: 0u128,    f15: 0u128,    f16: 0u128,    f17: 0u128,    f18: 0u128,    f19: 0u128,    f20: 0u128,    f21: 0u128,    f22: 0u128,    f23: 0u128,    f24: 0u128,    f25: 0u128,    f26: 0u128,    f27: 0u128,    f28: 0u128,    f29: 0u128,    f30: 0u128,    f31: 0u128  },  c5: {    f0: 0u128,    f1: 0u128,    f2: 0u128,    f3: 0u128,    f4: 0u128,    f5: 0u128,    f6: 0u128,    f7: 0u128,    f8: 0u128,    f9: 0u128,    f10: 0u128,    f11: 0u128,    f12: 0u128,    f13: 0u128,    f14: 0u128,    f15: 0u128,    f16: 0u128,    f17: 0u128,    f18: 0u128,    f19: 0u128,    f20: 0u128,    f21: 0u128,    f22: 0u128,    f23: 0u128,    f24: 0u128,    f25: 0u128,    f26: 0u128,    f27: 0u128,    f28: 0u128,    f29: 0u128,    f30: 0u128,    f31: 0u128  },  c6: {    f0: 0u128,    f1: 0u128,    f2: 0u128,    f3: 0u128,    f4: 0u128,    f5: 0u128,    f6: 0u128,    f7: 0u128,    f8: 0u128,    f9: 0u128,    f10: 0u128,    f11: 0u128,    f12: 0u128,    f13: 0u128,    f14: 0u128,    f15: 0u128,    f16: 0u128,    f17: 0u128,    f18: 0u128,    f19: 0u128,    f20: 0u128,    f21: 0u128,    f22: 0u128,    f23: 0u128,    f24: 0u128,    f25: 0u128,    f26: 0u128,    f27: 0u128,    f28: 0u128,    f29: 0u128,    f30: 0u128,    f31: 0u128  },  c7: {    f0: 0u128,    f1: 0u128,    f2: 0u128,    f3: 0u128,    f4: 0u128,    f5: 0u128,    f6: 0u128,    f7: 0u128,    f8: 0u128,    f9: 0u128,    f10: 0u128,    f11: 0u128,    f12: 0u128,    f13: 0u128,    f14: 0u128,    f15: 0u128,    f16: 0u128,    f17: 0u128,    f18: 0u128,    f19: 0u128,    f20: 0u128,    f21: 0u128,    f22: 0u128,    f23: 0u128,    f24: 0u128,    f25: 0u128,    f26: 0u128,    f27: 0u128,    f28: 0u128,    f29: 0u128,    f30: 0u128,    f31: 0u128  }}",
      "report": "{  c0: {    f0: 84855022739072527368193u128,    f1: 68385684764540665893611210958203650051u128,    f2: 242957950407643292263866366603922545911u128,    f3: 54648694067525505081604253854u128,    f4: 4082482497131797u128,    f5: 0u128,    f6: 0u128,    f7: 129127208515966861317u128,    f8: 233766822598046444780732758795436574693u128,    f9: 196218172098311655326695594710050546072u128,    f10: 0u128,    f11: 0u128,    f12: 153386052680309655679396867527014121204u128,    f13: 35972203959719964238382729092704599014u128,    f14: 0u128,    f15: 0u128,    f16: 0u128,    f17: 0u128,    f18: 0u128,    f19: 0u128,    f20: 65537u128,    f21: 0u128,    f22: 0u128,    f23: 0u128,    f24: 261416126709284881514438155237913112811u128,    f25: 0u128,    f26: 0u128,    f27: 0u128,    f28: 337324841058634346475366972519769706564u128,    f29: 252860127799780593534801600072839553239u128,    f30: 236169299281726223428842072154214868933u128,    f31: 195612957357288116730058683633947877804u128  },  c1: {    f0: 117891055671150134937207206768291420u128,    f1: 327718390601232644976585669983462482511u128,    f2: 24330412716767774705623998119162324926u128,    f3: 138829435947332207818351983315511379419u128,    f4: 17534128811673485667330409u128,    f5: 0u128,    f6: 0u128,    f7: 554597137599850363245001965568u128,    f8: 51321760518872024617203618802506399744u128,    f9: 67728825339782400665172072549140061414u128,    f10: 3840007777u128,    f11: 0u128,    f12: 158837950468731255509735392413912924160u128,    f13: 90434782647414738426891946114991426246u128,    f14: 4286301584u128,    f15: 0u128,    f16: 0u128,    f17: 0u128,    f18: 0u128,    f19: 0u128,    f20: 2814754062073856u128,    f21: 0u128,    f22: 0u128,    f23: 0u128,    f24: 324754746029249963345795058866300387328u128,    f25: 262713569315817736053191240715644376071u128,    f26: 396987308u128,    f27: 0u128,    f28: 154784207227359996978187994524398125056u128,    f29: 165436057910215533569203026795993875916u128,    f30: 326264497880770141808294999852069102498u128,    f31: 98517025443571631514782680799578348853u128  },  c2: {    f0: 12004732790720997080891679056550808575u128,    f1: 33355783264191645768789692391696894730u128,    f2: 60049829442654824440068874493786594074u128,    f3: 86749189800108151757823289210582680109u128,    f4: 89408317962157473941141852435021382996u128,    f5: 116247298448171836707225814442806559810u128,    f6: 153298516702326844018032793253697894448u128,    f7: 97503207721845674876966991394193684528u128,    f8: 92066185763862219525981875178096847482u128,    f9: 158631690561421924035459988786500419911u128,    f10: 76333970513925110025764547352733963623u128,    f11: 86951652772898462981681034850997918314u128,    f12: 94896799011537378893460037220868506201u128,    f13: 116147467564052018692635533112133645142u128,    f14: 86754362688545102779307753469975033145u128,    f15: 112119725805968183605533498525349401716u128,    f16: 108017770325421329463318335114491808837u128,    f17: 86837782966952094203466333913022481712u128,    f18: 104299154292433981337878436150804502124u128,    f19: 102970007423461191398703387622748865914u128,    f20: 158756673053749662613813693058116962644u128,    f21: 120250821724838927997570695467201021027u128,    f22: 90731620886030983844249335288351250259u128,    f23: 64167425784331583248880956763149597011u128,    f24: 158714297810016602898334694321548514394u128,    f25: 76136666399556079529596080858030625618u128,    f26: 104215935482822920403569083451176409465u128,    f27: 104039541035603526609816581170645779030u128,    f28: 108114213427665675835456091415639513459u128,    f29: 65471119637970862968276758529751402833u128,    f30: 137254884056849384459604142725565400405u128,    f31: 142769694527016630226411770057918542179u128  },  c3: {    f0: 89112578245003088838611936818941153130u128,    f1: 112186499542433954375491037642502208106u128,    f2: 90784520335163547732013059839169092170u128,    f3: 88098580733429188304785517654213749060u128,    f4: 13818678782623848242017603879574981974u128,    f5: 147820478781135256057168735290326086470u128,    f6: 158601004626878902877599539347155414609u128,    f7: 113324135867913542756083826620225910600u128,    f8: 74972654877031102216601080268178673456u128,    f9: 118640788039913225795845957010654258442u128,    f10: 57522524206617649377895238896809301572u128,    f11: 76395809444991429016706081744091699303u128,    f12: 104055463043983720312313305835522974568u128,    f13: 94896799018974010676587692096514886252u128,    f14: 66925915710382479181304097458923270998u128,    f15: 140080186552622183050687868903337785686u128,    f16: 66924476944912156571061685914505720377u128,    f17: 98992299697508934570972255816522545477u128,    f18: 132156009718758105502505635427965556333u128,    f19: 161279583780376529355820241584231039338u128,    f20: 86988240499279864031395599405181786217u128,    f21: 90851712646405306649273966649867921772u128,    f22: 86910759077318896229532865192996655702u128,    f23: 89481269114107147013099085316803215693u128,    f24: 94922557363533324889281353390439350605u128,    f25: 97414248676890686064111993804100224299u128,    f26: 64162090082353134852911296187142010690u128,    f27: 68061606517752099038461575957851489346u128,    f28: 97414252019350595078397302451144248628u128,    f29: 108006557258706241659985402300131793474u128,    f30: 147935278331152620242894529988311204400u128,    f31: 109335559370310372277484484735535696218u128  },  c4: {    f0: 108006557258706241659985474927626385237u128,    f1: 100088524550901356562081163050370548272u128,    f2: 86749273541778128252673674470155180655u128,    f3: 86806937632782324422938379499129489745u128,    f4: 100088524550901337654184547093126983761u128,    f5: 89501715209068986181232175188938414703u128,    f6: 104222184131274927152875686304401412417u128,    f7: 94714031756334156656567492352616190273u128,    f8: 96085101416419075191047717346100738371u128,    f9: 130645070357909842285010588752337528641u128,    f10: 86744078235532168310844955291706020916u128,    f11: 97455544295713879545243905514477798215u128,    f12: 130645070357909843409829925202292064586u128,    f13: 88130178435234664984192167563704226868u128,    f14: 108006554474245330756093469187236906817u128,    f15: 97466053372950493505749323473483811913u128,    f16: 88130178435234981346425003090388464738u128,    f17: 86806224810738141373754240919543170881u128,    f18: 110696878246818504645480466692776544593u128,    f19: 102689462638219053953715929901094429257u128,    f20: 86806224810789133026584909959423017282u128,    f21: 94964376728773384814305555424564234577u128,    f22: 86760182472435095491075972571471169875u128,    f23: 104039701701017929686387466547358679629u128,    f24: 94964376747633841451467273574021681473u128,    f25: 86743850775774187631488817526718220627u128,    f26: 86738642548474510552846856696003380822u128,    f27: 130645070357890500596716091135427166529u128,    f28: 108011726166852882164521742062605915188u128,    f29: 108005175979728448444544556956631253831u128,    f30: 137254802922232358469698402495009801553u128,    f31: 137259792715934442779251126941000429935u128  },  c5: {    f0: 86743671559825713225810936288001212741u128,    f1: 65185195345608567120154475649334068045u128,    f2: 65357457586765783080977191293115922537u128,    f3: 86998423942360155305591100450693936961u128,    f4: 154472602469542241641585002430073029429u128,    f5: 13549021765187881145134586349375603269u128,    f6: 152073519918233207828023866234766653003u128,    f7: 104038968442143258462312395470080267333u128,    f8: 60049831370206298086862839912815861828u128,    f9: 92065270838263588161724692358245264685u128,    f10: 102403394931704788846174182320797996114u128,    f11: 86744001382976538097282952900259301705u128,    f12: 110935596339372355082162529425482467687u128,    f13: 102757753904718435832159428816450184530u128,    f14: 13641730763236203195338302233747353409u128,    f15: 102751686145939161927243829626473498445u128,    f16: 110669981079482448319058586804081677637u128,    f17: 90850942152570950481689628423833072226u128,    f18: 90731562025364983292125121457312321878u128,    f19: 92269112234738910460234604810152927754u128,    f20: 93307304611000405257194885735877070165u128,    f21: 87034648393070435116482161781592515701u128,    f22: 153283362559674347752342369129799828042u128,    f23: 162608910905757605780267968350111599223u128,    f24: 90789749960275843698637110143409874241u128,    f25: 141298973437060242123296827944779741013u128,    f26: 162547292534704897884193116506469267525u128,    f27: 133532497310657633341072149250505861185u128,    f28: 113521522523369678774676020478138865223u128,    f29: 102694834785533074997134942172914010696u128,    f30: 130649998573320348463870441913035747154u128,    f31: 138624983733330959992385555618662732398u128  },  c6: {    f0: 92159075952097798322699461462172911460u128,    f1: 138863807754577485370649275968502855490u128,    f2: 102886685864261067444504776195468258659u128,    f3: 108089793406502879224265658521229355841u128,    f4: 150832375731722087451752855924366591303u128,    f5: 69521351739172570572808364160782783303u128,    f6: 102756435944532396704924302022142279993u128,    f7: 120084626246215828157538855856678449776u128,    f8: 153391974005147988715650772534534875957u128,    f9: 86837725691842740968865538395725325867u128,    f10: 68198029715524678187548970722900193876u128,    f11: 151917789119366573768094736235530178167u128,    f12: 114668498408916468643246581063172640578u128,    f13: 65533711314949557364595280228358172754u128,    f14: 94796928902038869219176506719306281324u128,    f15: 135832155811633629464337931991323143034u128,    f16: 88197415573835596094480142823048037698u128,    f17: 64188965780662179399672137617773840481u128,    f18: 65517870053603420032645768010385741665u128,    f19: 114575036516425533478059638766758409059u128,    f20: 76198953448334894703426641276428962938u128,    f21: 109263499842199640047903063019382268490u128,    f22: 64230461842459213854876536461822480708u128,    f23: 62729141095620952142801360698998932047u128,    f24: 143849141874647537468077485084531455339u128,    f25: 158423513593444577201225835437018140268u128,    f26: 109372291527157337602447472214371550545u128,    f27: 86645324449472246601531337146191921741u128,    f28: 88026069454382460688250206663376717159u128,    f29: 137296078894976326897348732728908139841u128,    f30: 117311701563535690054873511157550047828u128,    f31: 94621683947702260380930330556642702925u128  },  c7: {    f0: 157266585692263169432748518083816618295u128,    f1: 86677348170789000027156131147443557186u128,    f2: 162521268531709082938246788278115119159u128,    f3: 104038968442143258459157865742129909300u128,    f4: 60049831370206298086862839912815861828u128,    f5: 92065270838263588161724692358245264685u128,    f6: 102403394931704788846174182320797996114u128,    f7: 86744001382976675045910956351848401225u128,    f8: 137546180655561108076056018404869753191u128,    f9: 89678581623839706670222579498013315895u128,    f10: 13911653348267379143928883463380883815u128,    f11: 109616997758559601014350933934427423841u128,    f12: 157234559050145056110467932273002239827u128,    f13: 114720701137339631629859795251332461410u128,    f14: 157255307963199385955327972200009384258u128,    f15: 108094807033958817984488532228539573002u128,    f16: 70902625428892611236952963291692877175u128,    f17: 142566462633127032433531710020361869616u128,    f18: 87034648392996604956291596012756222279u128,    f19: 88130565149443671870324176594388781642u128,    f20: 90794921967916445037846635642051909684u128,    f21: 112057438767757703995190256887814518869u128,    f22: 88130827461549207523091912353999911497u128,    f23: 119880831756198184460899244703266522983u128,    f24: 108203921181293991924616096290221553495u128,    f25: 92118795085093294238435397575365903664u128,    f26: 132207609996927537498699975159394430037u128,    f27: 90851712725643296445717670572126652013u128,    f28: 90731885812260910872707057926404133206u128,    f29: 92159075952138897077551333410263680866u128,    f30: 114720701132697431966616368839344472387u128,    f31: 118920583898637034375179436867628646722u128  },  c8: {    f0: 120208391563958328903418431752285145928u128,    f1: 146496827975129713628545140622596143689u128,    f2: 162516038770122090537536818276459181893u128,    f3: 116184260795578461401620612162842740065u128,    f4: 97300828021546254909120508427600292423u128,    f5: 118931901008424116384729958666790529898u128,    f6: 100036301301652645797615676665268169834u128,    f7: 88259985781804142268996583522069936693u128,    f8: 120177358927007647960329552767271456359u128,    f9: 157281614327971246846144182102493985361u128,    f10: 96152543435324426254685485864430223665u128,    f11: 90732169228477843146456407899029977170u128,    f12: 143962642878211164384679925272543652712u128,    f13: 64080597579852368723578581181397102179u128,    f14: 141461154356937785131350677709217230435u128,    f15: 76027425043751003220509970687738075226u128,    f16: 76333687204450208078758577613038439540u128,    f17: 104215936829747759056653563243130086518u128,    f18: 150764531549494692607960815007211538518u128,    f19: 162536115989282966984643484707285716580u128,    f20: 108006593375585103515344389694009011819u128,    f21: 65471116944522798882642801786913697608u128,    f22: 135920100576416446773842260002668373077u128,    f23: 162546687390846958021578236361531540280u128,    f24: 86941307401230900785174445205576036458u128,    f25: 104195206872586117789496688062422275919u128,    f26: 73654539828148610787525649008678104943u128,    f27: 86760223015317314675068160783488144199u128,    f28: 153107513048634507624915175849216461364u128,    f29: 133334437843788124256415413717389227608u128,    f30: 60049826688636443598812574127591215442u128,    f31: 111994015668589605791723790244161858861u128  },  c9: {    f0: 2864421821820229u128,    f1: 0u128,    f2: 0u128,    f3: 0u128,    f4: 0u128,    f5: 0u128,    f6: 0u128,    f7: 0u128,    f8: 0u128,    f9: 0u128,    f10: 0u128,    f11: 0u128,    f12: 0u128,    f13: 0u128,    f14: 0u128,    f15: 0u128,    f16: 0u128,    f17: 0u128,    f18: 0u128,    f19: 0u128,    f20: 0u128,    f21: 0u128,    f22: 0u128,    f23: 0u128,    f24: 0u128,    f25: 0u128,    f26: 0u128,    f27: 0u128,    f28: 0u128,    f29: 0u128,    f30: 0u128,    f31: 0u128  }}",
      "address": "aleo1jpz58re8eydtcmxr3s2gdp4cdtumuyumnnvf2mmwq6shllkhusgqn53vja",
      "encodedPositions": {
        "data": {
          "Pos": 2,
          "Len": 1
        },
        "timestamp": {
          "Pos": 3,
          "Len": 1
        },
        "statusCode": {
          "Pos": 4,
          "Len": 1
        },
        "method": {
          "Pos": 17,
          "Len": 1
        },
        "responseFormat": {
          "Pos": 16,
          "Len": 1
        },
        "url": {
          "Pos": 5,
          "Len": 9
        },
        "selector": {
          "Pos": 14,
          "Len": 2
        },
        "encodingOptions": {
          "Pos": 18,
          "Len": 1
        },
        "requestHeaders": {
          "Pos": 19,
          "Len": 13
        },
        "optionalFields": {
          "Pos": 32,
          "Len": 4
        }
      },
      "encodedRequest": "{  c0: {    f0: 83078176003060725451284209119789060u128,    f1: 4194512u128,    f2: 0u128,    f3: 0u128,    f4: 200u128,    f5: 146741781957618190040822128409835696737u128,    f6: 152036601506766190083586533414400257325u128,    f7: 69438642371722949660980644949730617443u128,    f8: 133532659421421713743881801343056817714u128,    f9: 152038006197340572103123007711229066597u128,    f10: 66696071085301770748652136257525407604u128,    f11: 60086277185945482657482972579083134520u128,    f12: 146762247151254361341361560418480108080u128,    f13: 1836413791u128,    f14: 121200813359967904192723595955179970916u128,    f15: 23856u128,    f16: 0u128,    f17: 5522759u128,    f18: 36893488147419103234u128,    f19: 221360928884514619396u128,    f20: 13055389343712134841237569546u128,    f21: 13856407623565317u128,    f22: 156035770564570580066107481452631621659u128,    f23: 3900269670161044694030315513202u128,    f24: 162743726813863731210145153184655802480u128,    f25: 101188681738744639914108759155086748777u128,    f26: 149456393680743922584091041160660086377u128,    f27: 42816717959947032433996830433837802860u128,    f28: 132119436183189587630719372684727700264u128,    f29: 64042929165508395635299690384626118507u128,    f30: 61431102749981217983499061483759611950u128,    f31: 13875u128  },  c1: {    f0: 55340232221128654848u128,    f1: 0u128,    f2: 0u128,    f3: 0u128,    f4: 0u128,    f5: 0u128,    f6: 0u128,    f7: 0u128,    f8: 0u128,    f9: 0u128,    f10: 0u128,    f11: 0u128,    f12: 0u128,    f13: 0u128,    f14: 0u128,    f15: 0u128,    f16: 0u128,    f17: 0u128,    f18: 0u128,    f19: 0u128,    f20: 0u128,    f21: 0u128,    f22: 0u128,    f23: 0u128,    f24: 0u128,    f25: 0u128,    f26: 0u128,    f27: 0u128,    f28: 0u128,    f29: 0u128,    f30: 0u128,    f31: 0u128  },  c2: {    f0: 0u128,    f1: 0u128,    f2: 0u128,    f3: 0u128,    f4: 0u128,    f5: 0u128,    f6: 0u128,    f7: 0u128,    f8: 0u128,    f9: 0u128,    f10: 0u128,    f11: 0u128,    f12: 0u128,    f13: 0u128,    f14: 0u128,    f15: 0u128,    f16: 0u128,    f17: 0u128,    f18: 0u128,    f19: 0u128,    f20: 0u128,    f21: 0u128,    f22: 0u128,    f23: 0u128,    f24: 0u128,    f25: 0u128,    f26: 0u128,    f27: 0u128,    f28: 0u128,    f29: 0u128,    f30: 0u128,    f31: 0u128  },  c3: {    f0: 0u128,    f1: 0u128,    f2: 0u128,    f3: 0u128,    f4: 0u128,    f5: 0u128,    f6: 0u128,    f7: 0u128,    f8: 0u128,    f9: 0u128,    f10: 0u128,    f11: 0u128,    f12: 0u128,    f13: 0u128,    f14: 0u128,    f15: 0u128,    f16: 0u128,    f17: 0u128,    f18: 0u128,    f19: 0u128,    f20: 0u128,    f21: 0u128,    f22: 0u128,    f23: 0u128,    f24: 0u128,    f25: 0u128,    f26: 0u128,    f27: 0u128,    f28: 0u128,    f29: 0u128,    f30: 0u128,    f31: 0u128  },  c4: {    f0: 0u128,    f1: 0u128,    f2: 0u128,    f3: 0u128,    f4: 0u128,    f5: 0u128,    f6: 0u128,    f7: 0u128,    f8: 0u128,    f9: 0u128,    f10: 0u128,    f11: 0u128,    f12: 0u128,    f13: 0u128,    f14: 0u128,    f15: 0u128,    f16: 0u128,    f17: 0u128,    f18: 0u128,    f19: 0u128,    f20: 0u128,    f21: 0u128,    f22: 0u128,    f23: 0u128,    f24: 0u128,    f25: 0u128,    f26: 0u128,    f27: 0u128,    f28: 0u128,    f29: 0u128,    f30: 0u128,    f31: 0u128  },  c5: {    f0: 0u128,    f1: 0u128,    f2: 0u128,    f3: 0u128,    f4: 0u128,    f5: 0u128,    f6: 0u128,    f7: 0u128,    f8: 0u128,    f9: 0u128,    f10: 0u128,    f11: 0u128,    f12: 0u128,    f13: 0u128,    f14: 0u128,    f15: 0u128,    f16: 0u128,    f17: 0u128,    f18: 0u128,    f19: 0u128,    f20: 0u128,    f21: 0u128,    f22: 0u128,    f23: 0u128,    f24: 0u128,    f25: 0u128,    f26: 0u128,    f27: 0u128,    f28: 0u128,    f29: 0u128,    f30: 0u128,    f31: 0u128  },  c6: {    f0: 0u128,    f1: 0u128,    f2: 0u128,    f3: 0u128,    f4: 0u128,    f5: 0u128,    f6: 0u128,    f7: 0u128,    f8: 0u128,    f9: 0u128,    f10: 0u128,    f11: 0u128,    f12: 0u128,    f13: 0u128,    f14: 0u128,    f15: 0u128,    f16: 0u128,    f17: 0u128,    f18: 0u128,    f19: 0u128,    f20: 0u128,    f21: 0u128,    f22: 0u128,    f23: 0u128,    f24: 0u128,    f25: 0u128,    f26: 0u128,    f27: 0u128,    f28: 0u128,    f29: 0u128,    f30: 0u128,    f31: 0u128  },  c7: {    f0: 0u128,    f1: 0u128,    f2: 0u128,    f3: 0u128,    f4: 0u128,    f5: 0u128,    f6: 0u128,    f7: 0u128,    f8: 0u128,    f9: 0u128,    f10: 0u128,    f11: 0u128,    f12: 0u128,    f13: 0u128,    f14: 0u128,    f15: 0u128,    f16: 0u128,    f17: 0u128,    f18: 0u128,    f19: 0u128,    f20: 0u128,    f21: 0u128,    f22: 0u128,    f23: 0u128,    f24: 0u128,    f25: 0u128,    f26: 0u128,    f27: 0u128,    f28: 0u128,    f29: 0u128,    f30: 0u128,    f31: 0u128  }}",
      "requestHash": "296501215970795030411580168017829021648u128"
    },
    "attestationRequest": {
      "url": "archive-api.open-meteo.com/v1/archive?latitude=42.93869&longitude=-74.18819&start_date=2024-02-28&end_date=2024-02-28&daily=rain_sum",
      "requestMethod": "GET",
      "selector": "daily.rain_sum.[0]",
      "responseFormat": "json",
      "requestHeaders": {
        "Accept": "*/*",
        "DNT": "1",
        "Upgrade-Insecure-Requests": "1",
        "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"
      },
      "encodingOptions": {
        "value": "float",
        "precision": 2
      }
    }
  }
]

For a developer, the most interesting parts of the response will be the Attestation Data and Oracle Data.

Attestation Data is the data that was extracted, attested and verified. You can use it in your Web2.0 app however you please. It will always be a string in the response, as seen in the raw HTTP notarization response from the attestation target.

Oracle Data is an object that contains everything you need to use Attestation Data in an Aleo program.

About encoding data for Aleo#

In order to verify the Attestation Report about the data we needed a way to represent the Attestation Request and attestation results in Aleo programs and classic programming languages. The Attestation results consist of Attestation Data, response status code, and attestation timestamp. From now on, the Attestation Request + Attestation results combination will be called Report Data.

userData and Report Data

The report data is called userData in the SDK response! See OracleData.userData in JS SDK and OracleData.UserData in Go SDK.

The Aleo program that uses it should be able to hash it and make asserts on certain properties while also taking the least amount of space.

Below is a type that is used in Aleo programs for using Report Data. It's called ReportData and it consists of 8 512-byte data chunks.

Leo definition of ReportData
// a 512-byte data chunk
struct DataChunk {
    f0: u128,
    f1: u128,
    f2: u128,
    f3: u128,
    f4: u128,
    f5: u128,
    f6: u128,
    f7: u128,
    f8: u128,
    f9: u128,
    f10: u128,
    f11: u128,
    f12: u128,
    f13: u128,
    f14: u128,
    f15: u128,
    f16: u128,
    f17: u128,
    f18: u128,
    f19: u128,
    f20: u128,
    f21: u128,
    f22: u128,
    f23: u128,
    f24: u128,
    f25: u128,
    f26: u128,
    f27: u128,
    f28: u128,
    f29: u128,
    f30: u128,
    f31: u128
}

struct ReportData {
    c0: DataChunk,
    c1: DataChunk,
    c2: DataChunk,
    c3: DataChunk,
    c4: DataChunk,
    c5: DataChunk,
    c6: DataChunk,
    c7: DataChunk
}

The backend serializes the Report Data to bytes. It follows a defined order of serializing properties, using a defined serializing method.

Then all useful properties are padded and aligned in a certain way so that they can be encoded into Aleo u128s where a property occupies at least one u128.

It means that a program will be able to use the properties of Report Data by accessing them using chunk and property numbers, e.g. ReportData.c0.f2 - the first chunk, the third property.

To help you find the positions of the different properties, the Report Data in the SDK will contain positional information in AttestationResponse.oracleData.encodedPositions. In our example, the Attestation Data in Aleo will be in ReportData.c0.f2.

Position of Attestation Data

See the encoding documentation for the explanation of why it's in the third property of the first chunk.

Depending on encoding options, the Attestation Data can take more than one property

The Oracle supports serializing Attestation Data, in a way that Aleo program could use it, in the following 3 ways:

  • as a string
  • as an integer
  • as a floating point number

Attestation Data as a string#

To seriailze and encode Attestation Data as a string for Aleo, you set AttestationRequest.encodingOptions.value to string.

Since Aleo didn't support strings at the moment of development of the SDK, strings are serialized to bytes, split into chunks of 16 bytes, then encoded into one or more 16-byte numbers - Aleo's u128.

Encoding a string shorter than 16 bytes

Attestation Data: "Hello, world!"

Bytes: 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21

The bytes are padded with 0 to 16: 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21 00 00 00

Interpreting the byte array as little endian representation of a 16-byte number: 2645608968347327576478451524936

ReportData.c0.f2 will be 2645608968347327576478451524936u128

Encoding a string longer than 16 bytes

Attestation Data: "Your balance: 1000000BTC"

Bytes: 59 6f 75 72 20 62 61 6c 61 6e 63 65 3a 20 31 30 30 30 30 30 30 42 54 43

The bytes are padded with 0 to 16: 59 6f 75 72 20 62 61 6c 61 6e 63 65 3a 20 31 30 30 30 30 30 30 42 54 43 00 00 00 00 00 00 00 00

Interpreting the byte array as little endian representation of two 16-byte numbers: 64058020007463102039520502111813332825 4851575473319194672

ReportData.c0.f2 will be 64058020007463102039520502111813332825u128.

ReportData.c0.f3 will be 4851575473319194672u128.

Let's now look into using this encoded string in an Aleo program.

You can make assertions on single bytes, part of the string, or the whole string.

For the sake of simplicity, the following examples will not use the ReportData struct just yet.

Make assertions on the whole string

It's as simple as comparing two numbers.

1
2
3
4
5
6
7
8
program encoded_string_example.aleo {
    transition main(public input1: u128, public input2: u128) -> bool {
        // Assert that the text is "Your balance: 1000000BTC"
        assert_eq(input1, 64058020007463102039520502111813332825u128);
        assert_eq(input2, 4851575473319194672u128);
        return true;
    }
}

As input we will use the "Hello, world!" string encoded to 2645608968347327576478451524936u128.

$ leo run main 64058020007463102039520502111813332825u128 4851575473319194672u128
        Leo  Compiled 'main.leo' into Aleo instructions

Output true in 'encoded_string_example.aleo' is a literal, ensure this is intended
  Constraints

  'encoded_string_example.aleo/main' - 6 constraints (called 1 time)

➡️  Output

 true

        Leo  Finished 'encoded_string_example.aleo/main'
Make asserts on single bytes
program encoded_string_example.aleo {
    inline get_nth_byte(num: u128, n: u32) -> u8 {
        let shift: u32 = n * 8u32;
        let shifted_number: u128 = num.shr(shift);
        let byte: u8 = (shifted_number & 255u128) as u8;
        return byte;
    }

    transition main(public input: u128) -> bool {
        let char0: u8 = get_nth_byte(input, 0u32);

        // ASCII code for "H" is 72
        assert_eq(char0, 72u8);
        return true;
    }
}

As input we will use the "Hello, world!" string encoded to 2645608968347327576478451524936u128.

$ leo run main 2645608968347327576478451524936u128
        Leo  Compiled 'main.leo' into Aleo instructions

Output true in 'encoded_string_example.aleo' is a literal, ensure this is intended
  Constraints

  'encoded_string_example.aleo/main' - 3 constraints (called 1 time)

➡️  Output

 true

        Leo  Finished 'encoded_string_example.aleo/main'
Make asserts on a part of the text

For this example we will need to reconstruct a part of the string, then make it match the length of the input string, and use zeroes in place of the characters we are not interested in.

Let's try to prove that the string "Your balance: 1000000BTC" contains the substring "1000000". In this case we were unlucky because the string we want is split between two u128s.

  1. u128 - 59 6f 75 72 20 62 61 6c 61 6e 63 65 3a 20 31 30 - 64058020007463102039520502111813332825u128.
  2. u128 - 30 30 30 30 30 42 54 43 00 00 00 00 00 00 00 00 - 4851575473319194672u128.

We're interested in the bytes highlighted in bold.

We will construct 2 numbers that have those bytes in the same positions:

  1. 00 00 00 00 00 00 00 00 00 00 00 00 00 00 31 30 - 64057366343744168453180733213588324352u128
  2. 30 30 30 30 30 00 00 00 00 00 00 00 00 00 00 00 - 206966894640u128

This is how we could use it in Leo

1
2
3
4
5
6
7
8
program encoded_string_example.aleo {
    transition main(public input1: u128, public input2: u128) -> bool {
        // Assert that the text contains "1000000" in the last 2 bytes of input1 and the beginning of input2
        assert_eq(input1 & 64057366343744168453180733213588324352u128, 64057366343744168453180733213588324352u128);
        assert_eq(input2 & 206966894640u128, 206966894640u128);
        return true;
    }
}
$ leo run main 64058020007463102039520502111813332825u128 4851575473319194672u128
        Leo  Compiled 'main.leo' into Aleo instructions

Output true in 'encoded_string_example.aleo' is a literal, ensure this is intended
  Constraints

  'encoded_string_example.aleo/main' - 6 constraints (called 1 time)

➡️  Output

 true

        Leo  Finished 'encoded_string_example.aleo/main'

Attestation Data as an integer#

To seriailze and encode Attestation Data for Aleo as an unsigned integer up to 64 bits in size, you set AttestationRequest.encodingOptions.value to int.

When working with numbers, they must be encoded in a way that makes them look the same in an Aleo program and in the Report Data in the SDK.

To give a more specific example, if the Attestation Data is a number "42", we want our Aleo program to be able to assert it as ReportData.c0.f2 == 42u128.

As a developer you don't need to do anything. When backend prepares AttestationResponse.oracleData.userData that you see in the SDK response, it serializes the number as bytes in little-endian order and pads them to 16. Then the encoder turns those bytes into Aleo's u128, which produces the same number you have in the SDK response.

Example

SDK's example attestation response, where the irrelevant for this example properties were omitted:

[{
    "attestationData": "42"
    "attestationRequest": {
        "encodingOptions": {
            "value": "int",
        }
    }
    "oracleData": {
        "userData": "{  c0: {    f0: 83078176003060725451284209119789060u128,    f1: 4194512u128,    f2: 42u128,    f3: 1709730029u128, ..."
    }
}]

If you look at userData, you'll see that the encoded Attestation Data in c0.f2 is 42u128.

It makes it very easy to use in Aleo programs.

1
2
3
4
5
6
7
program meaning_of_life.aleo {
    transition main(answer: u128, public oracle_data: ReportData) -> u128 {
        assert(answer < oracle_data.c0.f2);

        return answer;
    }
}

AttestationData as a floating point number#

To seriailze and encode Attestation Data for Aleo as an unsigned integer up to 64 bits in size, you set AttestationRequest.encodingOptions.value to int. This is the only encoding option where you also need to provide desired precision. See the Guide to encoding options.

Not all floats can be encoded to an Aleo-compatible format at the moment.

The encoder implementation requires that the encoded value could be decoded to exactly the same floating point string as it was in the original Attestation Response.

When the backend encodes a floating point number, it first multiplies it by 10precision to get rid of the fractional part, then it works the same as the integer encoding.

Let's take a look at our weather example again

Example

SDK's example attestation response for the weather, where the irrelevant for this example properties were omitted:

[{
    "attestationData": "9.90"
    "attestationRequest": {
        "encodingOptions": {
            "value": "float",
            "precision": 2
        }
    }
    "oracleData": {
        "userData": "{  c0: {    f0: 83078176003060725451284209119789060u128,    f1: 4194512u128,    f2: 990u128,    f3: 1709730029u128, ..."
    }
}]

With precision 2, the 9.90 is encoded as 990u128. With precision 4, the 9.90 is encoded as 99000u128. With precision 1, the 9.90 is encoded as 99u128 etc.

1
2
3
4
5
program is_heavy_rain.aleo {
    transition main(public oracle_data: ReportData) {
        assert(oracle_data.c0.f2 > 400u128);
    }
}

About Attestation Report#

An Attestation Report is a report document about some data. The document is signed by the TEE enclave, and it contains additional information about the enclave such as unique ID, signer ID, security information.

Verifying the Attestation Report provides assurances that the enclave is running a specific version of source code, with some specific configuration. In case of Intel SGX, the Intel corporation acts as a security collateral. They also provide a list of combinations of software and hardware and their security level.

In the SDK's response, the Attestation Report is encoded in the attestationReport using Base64 encoding. This report is verified by the verification backend during the SDK's Notarize procedure. The verification backend makes assertions on the enclave unique ID during the verification - it uses the reproducibility of the enclave build process to find the expected unique ID.

The Attestation Report can include up to 64 bytes of user data. In our case, the data is Aleo's Poseidon8 hash of serialized and formatted Report Data.

The Attestation Report is an array of bytes that doesn't need serialization but it still needs to be formatted into a type compatible with Aleo.

We are reusing the DataChunk type from the beginning of this page and define the Attestation Report as Report.

struct Report {
    c0: DataChunk,
    c1: DataChunk,
    c2: DataChunk,
    c3: DataChunk,
    c4: DataChunk,
    c5: DataChunk,
    c6: DataChunk,
    c7: DataChunk,
    c8: DataChunk,
    c9: DataChunk
}

The 64 bytes of user data in the Report will be located in Report.c0.f24, Report.c0.f25, Report.c0.f26, and Report.c0.f27. The Poseidon8 hash of the user data is only 16 bytes - one u128.

program verify_report.aleo {
    transition main(data: ReportData, report: Report) -> bool {
        let data_hash: u128 = Poseidon8::hash_to_u128(data);
        // verify that the hash of the data signed by TEE and is included in the report
        assert_eq(data_hash, report.c0.f24);
        assert_eq(0u128, report.c0.f25);
        assert_eq(0u128, report.c0.f26);
        assert_eq(0u128, report.c0.f27);

        return true;
    }
}

Here are some more enclave flags and properties you can use:

  • report.c0.f4 - CPU security version
  • report.c0.f6 - enclave extended product ID
  • report.c0.f7 - enclave attributes - a bitmask:
    • assert_eq(report.c0.f7 & 1u128, 1u128) - assert that the enclave was initialized
    • assert_eq(report.c0.f7 & 2u128, 0u128) - assert that the enclave is not in debug mode
    • assert_eq(report.c0.f7 & 4u128, 4u128) - assert that the enclave is in 64-bit mode
  • report.c0.f8, report.c0.f9 - enclave's unique ID
  • report.c0.12, report.c0.f13 - enclave's signer ID
  • report.c0.f20 - 2 bytes of product ID + 2 bytes of security version + 2 bytes of config security version + 10 bytes of zeros
  • report.c0.f23 - enclave family ID
  • report.c0.f24-c0.f27 - 4 u128 (64 bytes) of report data

See Open Enclave SDK headers for SGX for more flags.

See Intel SGX and Open Enclave official documentation for more information.

Verifying Attestation Report signature#

The enclave Attestation Report from Intel SGX contains an ECDSA signature. At the moment Aleo doesn't support ECDSA signatures, and uses Schnorr instead.

To work around that, the backend will be generating an Aleo private key on startup. This key is then used to sign the whole Attestation Report after it is serialized and encoded for Aleo.

That way, the signature can be verified in an Aleo program.

In our weather attestation example you can find the signature in AttestationResponse.oracleData.signature. The public key of the key that created the signature can be found in AttestationResponse.oracleData.address.

Example

SDK's example attestation response for the weather, where the irrelevant for this example properties were omitted:

[
    {
        "timestamp": 1709730029,
        "oracleData": {
            "signature": "sign1x2kx7gssjd9a5davpazug4mj5k82634q5n4cha03akp734cwgsqwhrm4rfxpd4h6fpkz253v9yqp00s9fqpgpyfafcdjk08sy4fhvpps9fyug6x7nlr2ws0209uhsps4dv9g6998qnhc2g6f6vw4pug7qmefrdv65eg2d6v2lq2r5ezldy9rfgw2xrauwzfms3d5r793ldzsyjag5g2",
            "address": "aleo1jpz58re8eydtcmxr3s2gdp4cdtumuyumnnvf2mmwq6shllkhusgqn53vja",
        }
    }
]

This brings us to a full example of verifying the Attestation Report and Report Data.

Example
program verify_report.aleo {
    function verify_report(data: ReportData, report: Report, sig: signature, pub_key: address) -> bool {
        let data_hash: u128 = Poseidon8::hash_to_u128(data);

        // https://github.com/openenclave/openenclave/blob/e9a0423e3a0b242bccbe0b5b576e88b640f88f85/include/openenclave/bits/sgx/sgxtypes.h#L1088
        // verify enclave flags
        // chunk 0 field 7 contains enclave flags
        let enclave_flags: u128 = report.c0.f7;
        assert_eq(enclave_flags & 1u128, 1u128); // enclave initted
        assert_eq(enclave_flags & 2u128, 0u128); // enclave is not in debug mode
        assert_eq(enclave_flags & 4u128, 4u128); // enclave is in 64-bit mode

        // verify that the hash of the data signed by TEE and is included in the report
        assert_eq(data_hash, report.c0.f24);
        assert_eq(0u128, report.c0.f25);
        assert_eq(0u128, report.c0.f26);
        assert_eq(0u128, report.c0.f27);

        let report_hash: u128 = Poseidon8::hash_to_u128(report);

        // verify that the report was signed by TEE
        return signature::verify(sig, pub_key, report_hash);
    }
}

About request hash#

The oracle data contains an Encoded Request and an Encoded Request Hash. The Encoded Request is the same as the Report Data but with the Attestation Data and Attestation Timestamp zeroed out. Attestation Data and Timestamp are the only parts of Report Data that can be different every time you perform notarization. By zeroing out these 2 fields, we can create a constant Report Data, which is going to represent a request to the attestation target.

AttestationResponse.oracleData.encodedRequest

When an Aleo program is going to verify that a request was done using the correct parameters, like URL, Request Body, Request Headers etc., it can take the Report Data provided, replace the Attestation Data and the Timestamp with 0u128 and then compare the result with the constant UserData in the program.

You can also hash it and, for example, compare it with the expected hash to make sure the data comes from attesting the target with the desired parameters. When hashed, it's also easier to store in a mapping.

The Encoded Request Hash is created using Aleo's Poseidon8 hash as u128.

Using Request Hash

program check_request.aleo {
    // assume that the hash is stored in key 0u8
    mapping expected_request_hash: u8 => u128;

    transition check_request(public report_data: ReportData) {
        let first_data_chunk: DataChunk = DataChunk {
            f0: report_data.c0.f0,
            f1: report_data.c0.f1,
            f2: 0u128,
            f3: 0u128,
            f4: report_data.c0.f4,
            f5: report_data.c0.f5,
            f6: report_data.c0.f6,
            f7: report_data.c0.f7,
            f8: report_data.c0.f8,
            f9: report_data.c0.f9,
            f10: report_data.c0.f10,
            f11: report_data.c0.f11,
            f12: report_data.c0.f12,
            f13: report_data.c0.f13,
            f14: report_data.c0.f14,
            f15: report_data.c0.f15,
            f16: report_data.c0.f16,
            f17: report_data.c0.f17,
            f18: report_data.c0.f18,
            f19: report_data.c0.f19,
            f20: report_data.c0.f20,
            f21: report_data.c0.f21,
            f22: report_data.c0.f22,
            f23: report_data.c0.f23,
            f24: report_data.c0.f24,
            f25: report_data.c0.f25,
            f26: report_data.c0.f26,
            f27: report_data.c0.f27,
            f28: report_data.c0.f28,
            f29: report_data.c0.f29,
            f30: report_data.c0.f30,
            f31: report_data.c0.f31,
        };

        let request_data: ReportData = ReportData {
            c0: first_data_chunk,
            c1: report_data.c1,
            c2: report_data.c2,
            c3: report_data.c3,
            c4: report_data.c4,
            c5: report_data.c5,
            c6: report_data.c6,
            c7: report_data.c7
        };

        let request_hash: u128 = Poseidon8::hash_to_u128(request_data);

        return then finalize(request_hash);
    }

    finalize check_request(public request_hash: u128) {
        let expected_request_hash: u128 = Mapping::get(0u8);

        assert_eq(request_hash, expected_request_hash);
    }
}