Merge branch 'dev' into docs/reference-doc-sidebar

This commit is contained in:
John David Pressman 2020-02-18 14:34:42 -08:00
commit b0eeb596df
164 changed files with 24251 additions and 17514 deletions

View File

@ -80,9 +80,9 @@ dont-merge-to-master:
- public
.docker: &docker
image: docker:19
image: docker:19.03.5
services:
- docker:19-dind
- docker:19.03.5-dind
.before_script: &before_script
@ -112,6 +112,7 @@ local-dune-job:
only:
- merge_requests
- dev
- /^.*-run-dev$/
# Run a docker build without publishing to the registry
build-current-docker-image:
@ -136,10 +137,10 @@ build-and-publish-latest-docker-image:
- sh scripts/build_docker_image.sh
- sh scripts/test_cli.sh
- echo ${LIGO_REGISTRY_PASSWORD} | docker login -u ${LIGO_REGISTRY_USER} --password-stdin
- docker push ${LIGO_REGISTRY_IMAGE_BUILD:-ligolang/ligo}:next
- docker push ${LIGO_REGISTRY_IMAGE_BUILD:-ligolang/ligo}:$(if test "$CI_COMMIT_REF_NAME" = "dev"; then echo next; else echo next-attempt; fi)
rules:
# Only deploy docker when from the dev branch AND on the canonical ligolang/ligo repository
- if: '$CI_COMMIT_REF_NAME == "dev" && $CI_PROJECT_PATH == "ligolang/ligo"'
- if: '$CI_COMMIT_REF_NAME =~ /^(dev|.*-run-dev)$/ && $CI_PROJECT_PATH == "ligolang/ligo"'
when: always
# It'd be a good idea to generate those jobs dynamically,
@ -155,6 +156,7 @@ build-and-package-debian-9:
<<: *build_binary
only:
- dev
- /^.*-run-dev$/
build-and-package-debian-10:
<<: *docker
@ -171,6 +173,7 @@ build-and-package-debian-10:
only:
- merge_requests
- dev
- /^.*-run-dev$/
build-and-package-ubuntu-18-04:
<<: *docker
@ -183,6 +186,7 @@ build-and-package-ubuntu-18-04:
<<: *build_binary
only:
- dev
- /^.*-run-dev$/
build-and-package-ubuntu-19-04:
<<: *docker
@ -195,6 +199,7 @@ build-and-package-ubuntu-19-04:
<<: *build_binary
only:
- dev
- /^.*-run-dev$/
# Pages are deployed from dev, be careful not to override 'next'
# in case something gets merged into 'dev' while releasing.
@ -204,6 +209,12 @@ pages:
- if: '$CI_COMMIT_REF_NAME == "dev" && $CI_PROJECT_PATH == "ligolang/ligo"'
when: always
pages-attempt:
<<: *website_build
rules:
- if: '$CI_COMMIT_REF_NAME =~ /^.*-run-dev$/ && $CI_PROJECT_PATH == "ligolang/ligo"'
when: always
# WEBIDE jobs
run-webide-unit-tests:
@ -264,4 +275,3 @@ deploy-handoff:
rules:
- if: '$CI_COMMIT_REF_NAME == "dev"'
when: always

View File

@ -111,6 +111,27 @@ let%expect_test _ =
If you're not sure how to fix this error, you can
do one of the following:
* Visit our documentation: https://ligolang.org/docs/intro/what-and-why/
* Ask a question on our Discord: https://discord.gg/9rhYaEt
* Open a gitlab issue: https://gitlab.com/ligolang/ligo/issues/new
* Check the changelog by running 'ligo changelog' |}]
(*
This test is here to ensure compatibility with comparable pairs introduced in carthage
note that only "comb pairs" are allowed to be compared (would be beter if any pair would be comparable ?)
*)
let%expect_test _ =
run_ligo_good [ "interpret" ; "Set.literal [ (1,(2,3)) ; (2,(3,4)) ]" ; "--syntax=cameligo" ] ;
[%expect {|
set[( 2 , ( 3 , 4 ) ) , ( 1 , ( 2 , 3 ) )] |}];
run_ligo_bad [ "interpret" ; "Set.literal [ (1,2,3) ; (2,3,4) ]" ; "--syntax=cameligo" ] ;
[%expect {|
ligo: not a comparable type: pair (use (a,(b,c)) instead of (a,b,c))
If you're not sure how to fix this error, you can
do one of the following:
* Visit our documentation: https://ligolang.org/docs/intro/what-and-why/
* Ask a question on our Discord: https://discord.gg/9rhYaEt
* Open a gitlab issue: https://gitlab.com/ligolang/ligo/issues/new

View File

@ -97,7 +97,7 @@ let fetch_lambda_types (contract_ty:ex_ty) =
| _ -> simple_fail "failed to fetch lambda types"
let run_contract ?options (exp:Michelson.t) (exp_type:ex_ty) (input_michelson:Michelson.t) : run_res result =
let open! Tezos_raw_protocol_005_PsBabyM1 in
let open! Tezos_raw_protocol_006_PsCARTHA in
let%bind (Ex_ty input_ty, Ex_ty output_ty) = fetch_lambda_types exp_type in
let%bind input =
Trace.trace_tzresult_lwt (simple_error "error parsing input") @@
@ -127,7 +127,7 @@ let run_contract ?options (exp:Michelson.t) (exp_type:ex_ty) (input_michelson:Mi
| _ -> fail @@ Errors.unknown_failwith_type () )
let run_expression ?options (exp:Michelson.t) (exp_type:ex_ty) : run_res result =
let open! Tezos_raw_protocol_005_PsBabyM1 in
let open! Tezos_raw_protocol_006_PsCARTHA in
let (Ex_ty exp_type') = exp_type in
let exp = Michelson.strip_annots exp in
let top_level = Script_ir_translator.Lambda

View File

@ -20,6 +20,7 @@ module Ty = struct
let address_k = Address_key None
let timestamp_k = Timestamp_key None
let bytes_k = Bytes_key None
let pair_k a b = Pair_key ((a,None),(b,None),None)
(* let timestamp_k = Timestamp_key None *)
let unit = Unit_t None
@ -77,12 +78,30 @@ module Ty = struct
| TC_key_hash -> return key_hash_k
| TC_chain_id -> fail (not_comparable "chain_id")
let comparable_type : type_value -> ex_comparable_ty result = fun tv ->
let comparable_leaf : type a. (a, _) comparable_struct -> (a , leaf) comparable_struct result =
fun a ->
match a with
| Pair_key _ -> fail (not_comparable "pair (use (a,(b,c)) instead of (a,b,c))")
| Int_key annot -> ok (Int_key annot)
| Nat_key annot -> ok (Nat_key annot)
| String_key annot -> ok (String_key annot)
| Bytes_key annot -> ok (Bytes_key annot)
| Mutez_key annot -> ok (Mutez_key annot)
| Bool_key annot -> ok (Bool_key annot)
| Key_hash_key annot -> ok (Key_hash_key annot)
| Timestamp_key annot -> ok (Timestamp_key annot)
| Address_key annot -> ok (Address_key annot)
let rec comparable_type : type_value -> ex_comparable_ty result = fun tv ->
match tv with
| T_base b -> comparable_type_base b
| T_function _ -> fail (not_comparable "function")
| T_or _ -> fail (not_comparable "or")
| T_pair _ -> fail (not_comparable "pair")
| T_pair ((_,a),(_,b)) ->
let%bind (Ex_comparable_ty a') = comparable_type a in
let%bind (Ex_comparable_ty b') = comparable_type b in
let%bind a'' = comparable_leaf a' in
ok @@ Ex_comparable_ty (pair_k a'' b')
| T_map _ -> fail (not_comparable "map")
| T_big_map _ -> fail (not_comparable "big_map")
| T_list _ -> fail (not_comparable "list")

View File

@ -166,7 +166,7 @@ let literal ppf (l : literal) =
| Literal_string s ->
fprintf ppf "%S" s
| Literal_bytes b ->
fprintf ppf "0x%s" @@ Bytes.to_string @@ Bytes.escaped b
fprintf ppf "0x%a" Hex.pp (Hex.of_bytes b)
| Literal_address s ->
fprintf ppf "@%S" s
| Literal_operation _ ->

View File

@ -0,0 +1,5 @@
open PP
let%expect_test _ =
Format.printf "%a" literal (Literal_bytes (Bytes.of_string "foo")) ;
[%expect{| 0x666f6f |}]

View File

@ -6,7 +6,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="The LIGO Playground for learning LIGO" />
<link rel="apple-touch-icon" href="logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/

View File

@ -7,6 +7,7 @@ import { Examples } from './components/examples';
import { FloatButtonComponent } from './components/float-button';
import { HeaderComponent } from './components/header';
import { TabsPanelComponent } from './components/tabs-panel';
import { TooltipContainer } from './components/tooltip';
import configureStore from './configure-store';
const store = configureStore();
@ -48,6 +49,7 @@ const App: React.FC = () => {
href="https://discord.gg/9rhYaEt"
></FloatButtonComponent>
</FeedbackContainer>
<TooltipContainer></TooltipContainer>
</Provider>
);
};

View File

@ -3,16 +3,25 @@ import { useDispatch, useSelector } from 'react-redux';
import styled from 'styled-components';
import { AppState } from '../redux/app';
import { ChangeEntrypointAction, CompileState } from '../redux/compile';
import { Group, Input, Label } from './inputs';
import { ChangeEntrypointAction, ChangeMichelsonFormatAction, CompileState, MichelsonFormat } from '../redux/compile';
import { CheckboxComponent } from './checkbox';
import { Group, HGroup, Input, Label } from './inputs';
const Container = styled.div``;
const Checkbox = styled(CheckboxComponent)`
margin-right: 0.3em;
`;
export const CompilePaneComponent = () => {
const dispatch = useDispatch();
const entrypoint = useSelector<AppState, CompileState['entrypoint']>(
state => state.compile.entrypoint
);
const michelsonFormat = useSelector<
AppState,
CompileState['michelsonFormat']
>(state => state.compile.michelsonFormat);
return (
<Container>
@ -26,6 +35,19 @@ export const CompilePaneComponent = () => {
}
></Input>
</Group>
<HGroup>
<Checkbox
checked={michelsonFormat === MichelsonFormat.Json}
onChanged={value =>
dispatch({
...new ChangeMichelsonFormatAction(
value ? MichelsonFormat.Json : MichelsonFormat.Text
)
})
}
></Checkbox>
<Label htmlFor="michelsonFormat">Output michelson in JSON format</Label>
</HGroup>
</Container>
);
};

View File

@ -1,5 +1,7 @@
import React, { useState } from 'react';
import styled, { css } from 'styled-components';
import React from 'react';
import styled from 'styled-components';
import { Tooltip } from './tooltip';
const Container = styled.div`
display: flex;
@ -36,46 +38,16 @@ const Button = styled.a`
}
`;
const Tooltip = styled.div<{ visible?: boolean }>`
position: absolute;
pointer-events: none;
z-index: 3;
white-space: nowrap;
transform: translateX(-6.5em);
font-size: var(--font_sub_size);
color: var(--tooltip_foreground);
background-color: var(--tooltip_background);
border-radius: 6px;
padding: 5px 10px;
opacity: 0;
transition: opacity 0.2s ease 0.2s;
${props =>
props.visible &&
css`
opacity: 1;
`}
`;
export const FloatButtonComponent = (props: {
tooltip: string;
text: string;
href: string;
className?: string;
}) => {
const [isTooltipShowing, setShowTooltip] = useState(false);
return (
<Container className={props.className}>
<Tooltip visible={isTooltipShowing}>{props.tooltip}</Tooltip>
<Button
onMouseOver={() => setShowTooltip(true)}
onMouseOut={() => setShowTooltip(false)}
href={props.href}
target="_blank"
rel="noopener noreferrer"
>
<Tooltip position="left">{props.tooltip}</Tooltip>
<Button href={props.href} target="_blank" rel="noopener noreferrer">
{props.text}
</Button>
</Container>

View File

@ -7,6 +7,7 @@ import { AppState } from '../redux/app';
import { CommandState } from '../redux/command';
import { DoneLoadingAction, LoadingState } from '../redux/loading';
import { ResultState } from '../redux/result';
import { OutputToolbarComponent } from './output-toolbar';
const Container = styled.div<{ visible?: boolean }>`
position: absolute;
@ -15,8 +16,8 @@ const Container = styled.div<{ visible?: boolean }>`
height: 100%;
font-family: Menlo, Monaco, 'Courier New', monospace;
overflow: scroll;
display: flex;
flex-direction: column;
transform: translateX(100%);
transition: transform 0.2s ease-in;
@ -42,9 +43,9 @@ const CancelButton = styled.div`
const Output = styled.div`
flex: 1;
padding: 0.8em;
padding: 0 0.5em 0.5em 0.5em;
display: flex;
overflow: scroll;
/* This font size is used to calcuate spinner size */
font-size: 1em;
`;
@ -65,6 +66,37 @@ const Pre = styled.pre`
margin: 0;
`;
function copyOutput(el: HTMLElement | null) {
if (el) {
const range = document.createRange();
range.selectNodeContents(el);
const selection = window.getSelection();
if (selection) {
selection.removeAllRanges();
selection.addRange(range);
document.execCommand('copy');
}
}
}
function downloadOutput(el: HTMLElement | null) {
if (el) {
const anchor = document.createElement('a');
anchor.setAttribute(
'href',
'data:text/plain;charset=utf-8,' + encodeURIComponent(el.innerHTML)
);
anchor.setAttribute('download', 'output.txt');
anchor.style.display = 'none';
document.body.appendChild(anchor);
anchor.click();
document.body.removeChild(anchor);
}
}
export const OutputTabComponent = (props: {
selected?: boolean;
onCancel?: () => void;
@ -85,13 +117,14 @@ export const OutputTabComponent = (props: {
const dispatch = useDispatch();
const outputRef = useRef(null);
const outputRef = useRef<HTMLDivElement>(null);
const preRef = useRef<HTMLPreElement>(null);
const [spinnerSize, setSpinnerSize] = useState(50);
useEffect(() => {
const htmlElement = (outputRef.current as unknown) as HTMLElement;
const outputEl = (outputRef.current as unknown) as HTMLElement;
const fontSize = window
.getComputedStyle(htmlElement, null)
.getComputedStyle(outputEl, null)
.getPropertyValue('font-size');
setSpinnerSize(parseFloat(fontSize) * 3);
@ -99,6 +132,12 @@ export const OutputTabComponent = (props: {
return (
<Container visible={props.selected}>
{output.length !== 0 && (
<OutputToolbarComponent
onCopy={() => copyOutput(preRef.current)}
onDownload={() => downloadOutput(preRef.current)}
></OutputToolbarComponent>
)}
<Output id="output" ref={outputRef}>
{loading.loading && (
<LoadingContainer>
@ -122,7 +161,7 @@ export const OutputTabComponent = (props: {
</LoadingContainer>
)}
{!loading.loading &&
((output.length !== 0 && <Pre>{output}</Pre>) ||
((output.length !== 0 && <Pre ref={preRef}>{output}</Pre>) ||
(contract.length !== 0 && (
<span>
The contract was successfully deployed to the babylonnet test

View File

@ -0,0 +1,78 @@
import { faCopy, faDownload } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import React from 'react';
import styled from 'styled-components';
import { Tooltip } from './tooltip';
const Container = styled.div`
display: flex;
justify-content: flex-start;
padding: 0.2em 0.5em;
z-index: 3;
`;
const Action = styled.div`
z-index: 3;
position: relative;
margin: 4px 6px;
cursor: pointer;
opacity: 0.5;
color: #444;
::before {
content: '';
display: block;
position: absolute;
z-index: -1;
bottom: -4px;
left: -4px;
right: -4px;
top: -4px;
border-radius: 4px;
background: none;
box-sizing: border-box;
opacity: 0;
transform: scale(0);
transition-property: transform, opacity;
transition-duration: 0.15s;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
:hover::before {
background-color: rgba(32, 33, 36, 0.059);
opacity: 1;
transform: scale(1);
}
:hover {
opacity: 1;
}
&:first-child {
margin-left: 0;
}
&:last-child {
margin-right: 0;
}
`;
export const OutputToolbarComponent = (props: {
onCopy?: () => void;
onDownload?: () => void;
}) => {
return (
<Container>
<Action onClick={() => props.onCopy && props.onCopy()}>
<FontAwesomeIcon icon={faCopy}></FontAwesomeIcon>
<Tooltip>Copy</Tooltip>
</Action>
<Action onClick={() => props.onDownload && props.onDownload()}>
<FontAwesomeIcon icon={faDownload}></FontAwesomeIcon>
<Tooltip>Download</Tooltip>
</Action>
</Container>
);
};

View File

@ -8,6 +8,7 @@ import styled, { css } from 'styled-components';
import { AppState } from '../redux/app';
import { ChangeShareLinkAction, ShareState } from '../redux/share';
import { share } from '../services/api';
import { Tooltip } from './tooltip';
const Container = styled.div`
display: flex;
@ -96,26 +97,6 @@ const Input = styled.input<{ visible?: boolean }>`
`}
`;
const Tooltip = styled.div<{ visible?: boolean }>`
position: absolute;
pointer-events: none;
z-index: 3;
transform: translateY(2.5em);
font-size: var(--font_sub_size);
color: var(--tooltip_foreground);
background-color: var(--tooltip_background);
border-radius: 6px;
padding: 5px 10px;
opacity: 0;
transition: opacity 0.2s ease 0.2s;
${props =>
props.visible &&
css`
opacity: 1;
`}
`;
const shareAction = () => {
return async function(dispatch: Dispatch, getState: () => AppState) {
try {
@ -138,7 +119,6 @@ export const ShareComponent = () => {
state => state.share.link
);
const [clicked, setClicked] = useState(false);
const [isTooltipShowing, setShowTooltip] = useState(false);
const SHARE_TOOLTIP = 'Share code';
const COPY_TOOLTIP = 'Copy link';
@ -149,14 +129,12 @@ export const ShareComponent = () => {
if (shareLink) {
if (inputEl.current && copy(inputEl.current)) {
setTooltipMessage(COPIED_TOOLTIP);
setShowTooltip(true);
} else {
setClicked(true);
setTooltipMessage(COPY_TOOLTIP);
}
} else {
setClicked(false);
setShowTooltip(false);
setTooltipMessage(SHARE_TOOLTIP);
}
}, [shareLink]);
@ -177,9 +155,7 @@ export const ShareComponent = () => {
if (tooltipMessage === COPIED_TOOLTIP) {
setTooltipMessage(COPY_TOOLTIP);
}
setShowTooltip(true);
}}
onMouseOut={() => setShowTooltip(false)}
onClick={() => {
if (!shareLink) {
dispatch(shareAction());
@ -193,7 +169,7 @@ export const ShareComponent = () => {
>
<Label visible={!clicked}>Share</Label>
<Copy visible={clicked}></Copy>
<Tooltip visible={isTooltipShowing}>{tooltipMessage}</Tooltip>
<Tooltip>{tooltipMessage}</Tooltip>
</Button>
</Container>
);

View File

@ -69,7 +69,11 @@ export const TabsPanelComponent = () => {
<Container>
<Header>
{TABS.map(tab => (
<Tab id={tab.id} selected={selectedTab.index === tab.index}>
<Tab
key={tab.id}
id={tab.id}
selected={selectedTab.index === tab.index}
>
<Label onClick={() => selectTab(tab)}>{tab.label}</Label>
</Tab>
))}

View File

@ -0,0 +1,104 @@
import React, { createElement, useEffect, useRef, useState } from 'react';
import { render } from 'react-dom';
import styled from 'styled-components';
const Container = styled.div`
position: fixed;
z-index: 1000;
top: 0;
left: 0;
height: 100%;
width: 100%;
pointer-events: none;
`;
export const StyledTooltip = styled.div<{
visible: boolean;
x: string;
y: string;
}>`
position: fixed;
pointer-events: none;
z-index: 1001;
font-size: var(--font_sub_size);
color: var(--tooltip_foreground);
background-color: var(--tooltip_background);
border-radius: 6px;
padding: 5px 10px;
opacity: 0;
transition: opacity 0.2s ease 0.2s;
transform-origin: center;
${({ x, y }) => `transform: translate(calc(${x}), calc(${y}));`}
${({ visible }) => visible && `opacity: 1;`}
`;
const TOOLTIP_CONTAINER_ID = 'tooltip-container';
type Position = 'top' | 'bottom' | 'left' | 'right';
export const TooltipContainer = () => {
return <Container id={TOOLTIP_CONTAINER_ID}></Container>;
};
function calcX(triggerRect: ClientRect, position?: Position) {
if ('left' === position) {
return `${triggerRect.left - 10}px - 100%`;
} else if ('right' === position) {
return `${triggerRect.right + 10}px`;
}
return `${triggerRect.left + triggerRect.width / 2}px - 50%`;
}
function calcY(triggerRect: ClientRect, position?: string) {
if ('top' === position) {
return `${triggerRect.top - 10}px - 100%`;
} else if (!position || 'bottom' === position) {
return `${triggerRect.bottom + 10}px`;
}
return `${triggerRect.top + triggerRect.height / 2}px - 50%`;
}
export const Tooltip = (props: { position?: Position; children: any }) => {
const ref = useRef<HTMLDivElement>(null);
const [isTooltipVisible, setTooltipVisible] = useState(false);
const renderTooltip = (visible: boolean, triggerRect: ClientRect) => {
const tooltip = createElement(
StyledTooltip,
{
visible,
x: calcX(triggerRect, props.position),
y: calcY(triggerRect, props.position)
},
props.children
);
render(tooltip, document.getElementById(TOOLTIP_CONTAINER_ID));
};
useEffect(() => {
if (ref.current) {
const trigger = (ref.current as HTMLElement).parentElement;
if (trigger) {
if (isTooltipVisible) {
renderTooltip(true, trigger.getBoundingClientRect());
}
trigger.onmouseenter = _ => {
renderTooltip(true, trigger.getBoundingClientRect());
setTooltipVisible(true);
};
trigger.onmouseleave = _ => {
renderTooltip(false, trigger.getBoundingClientRect());
setTooltipVisible(false);
};
}
}
});
return <div ref={ref}></div>;
};

View File

@ -50,6 +50,7 @@
--tooltip_foreground: white;
--tooltip_background: rgba(0, 0, 0, 0.75) /*#404040*/;
--label_foreground: rgba(153, 153, 153, 1);
}
body {

View File

@ -16,7 +16,8 @@ export class CompileAction extends CancellableAction {
const michelsonCode = await compileContract(
editor.language,
editor.code,
compileState.entrypoint
compileState.entrypoint,
compileState.michelsonFormat
);
if (this.isCancelled()) {

View File

@ -6,11 +6,13 @@ export enum MichelsonFormat {
}
export enum ActionType {
ChangeEntrypoint = 'compile-change-entrypoint'
ChangeEntrypoint = 'compile-change-entrypoint',
ChangeMichelsonFormat = 'compile-change-michelson-format'
}
export interface CompileState {
entrypoint: string;
michelsonFormat: MichelsonFormat;
}
export class ChangeEntrypointAction {
@ -18,10 +20,19 @@ export class ChangeEntrypointAction {
constructor(public payload: CompileState['entrypoint']) {}
}
type Action = ChangeEntrypointAction | ChangeSelectedExampleAction;
export class ChangeMichelsonFormatAction {
public readonly type = ActionType.ChangeMichelsonFormat;
constructor(public payload: CompileState['michelsonFormat']) {}
}
type Action =
| ChangeEntrypointAction
| ChangeMichelsonFormatAction
| ChangeSelectedExampleAction;
const DEFAULT_STATE: CompileState = {
entrypoint: ''
entrypoint: '',
michelsonFormat: MichelsonFormat.Text
};
export default (state = DEFAULT_STATE, action: Action): CompileState => {
@ -36,6 +47,12 @@ export default (state = DEFAULT_STATE, action: Action): CompileState => {
...state,
entrypoint: action.payload
};
}
return state;
case ActionType.ChangeMichelsonFormat:
return {
...state,
michelsonFormat: action.payload
};
default:
return state;
}
};

View File

@ -1,4 +1,8 @@
import { ActionType as CompileActionType, ChangeEntrypointAction as ChangeCompileEntrypointAction } from './compile';
import {
ActionType as CompileActionType,
ChangeEntrypointAction as ChangeCompileEntrypointAction,
ChangeMichelsonFormatAction,
} from './compile';
import {
ActionType as DeployActionType,
ChangeEntrypointAction as ChangeDeployEntrypointAction,
@ -40,6 +44,7 @@ type Action =
| ChangeCodeAction
| ChangeLanguageAction
| ChangeCompileEntrypointAction
| ChangeMichelsonFormatAction
| ChangeDeployEntrypointAction
| ChangeDeployStorageAction
| UseTezBridgeAction
@ -61,7 +66,6 @@ export default (state = DEFAULT_STATE, action: Action): ShareState => {
case CompileActionType.ChangeEntrypoint:
case DeployActionType.ChangeEntrypoint:
case DeployActionType.ChangeStorage:
case DeployActionType.UseTezBridge:
case DryRunActionType.ChangeEntrypoint:
case DryRunActionType.ChangeParameters:
case DryRunActionType.ChangeStorage:

View File

@ -30,7 +30,7 @@ export async function compileExpression(
) {
const response = await axios.post('/api/compile-expression', {
syntax,
expression,
expression: `${expression}`,
format
});
return response.data;
@ -64,14 +64,24 @@ export async function share({
evaluateValue,
evaluateFunction
}: Partial<AppState>) {
const response = await axios.post('/api/share', {
const params = {
editor,
compile,
dryRun,
deploy,
evaluateValue,
evaluateFunction
});
};
// We don't want to store the following configuration
if (params.compile) {
delete params.compile.michelsonFormat;
}
if (params.deploy) {
delete params.deploy.useTezBridge;
}
const response = await axios.post('/api/share', params);
return response.data;
}

View File

@ -1,12 +1,12 @@
import { Request, Response } from 'express';
import { loadDefaultState } from '../load-state';
import { logger } from '../logger';
import latestSchema from '../schemas/share-latest';
import { storage } from '../storage';
import { FileNotFoundError } from '../storage/interface';
import { logger } from '../logger';
export function createSharedLinkHandler(
export function sharedLinkHandler(
appBundleDirectory: string,
template: (state: string) => string
) {

View File

@ -9,9 +9,9 @@ import { dryRunHandler } from './handlers/dry-run';
import { evaluateValueHandler } from './handlers/evaluate-value';
import { runFunctionHandler } from './handlers/run-function';
import { shareHandler } from './handlers/share';
import { createSharedLinkHandler } from './handlers/shared-link';
import { sharedLinkHandler } from './handlers/shared-link';
import { loadDefaultState } from './load-state';
import { loggerMiddleware, errorLoggerMiddleware } from './logger';
import { errorLoggerMiddleware, loggerMiddleware } from './logger';
var bodyParser = require('body-parser');
var escape = require('escape-html');
@ -47,7 +47,7 @@ app.use('^/$', async (_, res) =>
app.use(express.static(appBundleDirectory));
app.get(
`/p/:hash([0-9a-zA-Z\-\_]+)`,
createSharedLinkHandler(appBundleDirectory, template)
sharedLinkHandler(appBundleDirectory, template)
);
app.post('/api/compile-contract', compileContractHandler);
app.post('/api/compile-expression', compileExpressionHandler);

View File

@ -37,12 +37,30 @@ export async function loadDefaultState(appBundleDirectory: string) {
);
const defaultExample = JSON.parse(example);
defaultState.compile = defaultExample.compile;
defaultState.dryRun = defaultExample.dryRun;
defaultState.deploy = defaultExample.deploy;
defaultState.evaluateValue = defaultExample.evaluateValue;
defaultState.evaluateFunction = defaultExample.evaluateFunction;
defaultState.editor = defaultExample.editor;
defaultState.compile = {
...defaultState.compile,
...defaultExample.compile
};
defaultState.dryRun = {
...defaultState.dryRun,
...defaultExample.dryRun
};
defaultState.deploy = {
...defaultState.deploy,
...defaultExample.deploy
};
defaultState.evaluateValue = {
...defaultState.evaluateValue,
...defaultExample.evaluateValue
};
defaultState.evaluateFunction = {
...defaultState.evaluateFunction,
...defaultExample.evaluateFunction
};
defaultState.editor = {
...defaultState.editor,
...defaultExample.editor
};
defaultState.examples.selected = defaultExample;
}

View File

@ -18,7 +18,9 @@ export abstract class Migration {
}
throw new Error(
`Unable to migrate ${data}. Reached the end of the migration chain.`
`Unable to migrate ${JSON.stringify(
data
)}. Reached the end of the migration chain.`
);
}
return value;

View File

@ -3,6 +3,6 @@
(public_name tezos-memory-proto-alpha)
(libraries
tezos-protocol-environment
tezos-protocol-005-PsBabyM1
tezos-protocol-006-PsCARTHA
)
)

View File

@ -1,9 +1,9 @@
module Name = struct let name = "alpha" end
module Alpha_environment = Tezos_protocol_005_PsBabyM1.Protocol.Environment
module Alpha_environment = Tezos_protocol_006_PsCARTHA.Protocol.Environment
type alpha_error = Alpha_environment.Error_monad.error
type 'a alpha_tzresult = 'a Alpha_environment.Error_monad.tzresult
module Alpha_error_monad = Alpha_environment.Error_monad
module Proto = Tezos_protocol_005_PsBabyM1
module Proto = Tezos_protocol_006_PsCARTHA
include Proto

View File

@ -10,7 +10,7 @@ bug-reports: "https://gitlab.com/ligolang/tezos/issues"
depends: [
"dune"
"tezos-protocol-environment"
"tezos-protocol-005-PsBabyM1"
"tezos-protocol-006-PsCARTHA"
]
build: [
["dune" "build" "-p" name]

View File

@ -4,7 +4,7 @@
(libraries
tezos-error-monad
tezos-stdlib-unix
tezos-protocol-005-PsBabyM1-parameters
tezos-protocol-006-PsCARTHA-parameters
tezos-memory-proto-alpha
simple-utils
tezos-utils

View File

@ -105,7 +105,7 @@ module Context_init = struct
Pervasives.failwith "Must have one account with a roll to bake";
(* Check there is at least one roll *)
let constants : Constants_repr.parametric = Tezos_protocol_005_PsBabyM1_parameters.Default_parameters.constants_test in
let constants : Constants_repr.parametric = Tezos_protocol_006_PsCARTHA_parameters.Default_parameters.constants_test in
check_constants_consistency constants >>=? fun () ->
let hash =

View File

@ -41,7 +41,7 @@ depends: [
"tezos-data-encoding"
"tezos-protocol-environment"
"tezos-protocol-alpha"
"tezos-protocol-005-PsBabyM1-parameters"
"tezos-protocol-006-PsCARTHA"
"michelson-parser"
"simple-utils"
"tezos-utils"

View File

@ -25,80 +25,86 @@
open Protocol
let constants_mainnet = Constants_repr.{
let constants_mainnet =
Constants_repr.
{
preserved_cycles = 5;
blocks_per_cycle = 4096l;
blocks_per_commitment = 32l;
blocks_per_roll_snapshot = 256l;
blocks_per_voting_period = 32768l;
time_between_blocks =
List.map Period_repr.of_seconds_exn [ 60L ; 40L ] ;
time_between_blocks = List.map Period_repr.of_seconds_exn [60L; 40L];
endorsers_per_block = 32;
hard_gas_limit_per_operation = Z.of_int 800_000 ;
hard_gas_limit_per_block = Z.of_int 8_000_000 ;
proof_of_work_threshold =
Int64.(sub (shift_left 1L 46) 1L) ;
hard_gas_limit_per_operation = Z.of_int 1_040_000;
hard_gas_limit_per_block = Z.of_int 10_400_000;
proof_of_work_threshold = Int64.(sub (shift_left 1L 46) 1L);
tokens_per_roll = Tez_repr.(mul_exn one 8_000);
michelson_maximum_type_size = 1000;
seed_nonce_revelation_tip = begin
match Tez_repr.(one /? 8L) with
| Ok c -> c
| Error _ -> assert false
end ;
seed_nonce_revelation_tip =
(match Tez_repr.(one /? 8L) with Ok c -> c | Error _ -> assert false);
origination_size = 257;
block_security_deposit = Tez_repr.(mul_exn one 512);
endorsement_security_deposit = Tez_repr.(mul_exn one 64);
block_reward = Tez_repr.(mul_exn one 16) ;
endorsement_reward = Tez_repr.(mul_exn one 2) ;
baking_reward_per_endorsement =
Tez_repr.[of_mutez_exn 1_250_000L; of_mutez_exn 187_500L];
endorsement_reward =
Tez_repr.[of_mutez_exn 1_250_000L; of_mutez_exn 833_333L];
hard_storage_limit_per_operation = Z.of_int 60_000;
cost_per_byte = Tez_repr.of_mutez_exn 1_000L;
test_chain_duration = Int64.mul 32768L 60L;
quorum_min = 20_00l ; (* quorum is in centile of a percentage *)
quorum_min = 20_00l;
(* quorum is in centile of a percentage *)
quorum_max = 70_00l;
min_proposal_quorum = 5_00l;
initial_endorsers = 24;
delay_per_missing_endorsement = Period_repr.of_seconds_exn 8L;
}
let constants_sandbox = Constants_repr.{
let constants_sandbox =
Constants_repr.
{
constants_mainnet with
preserved_cycles = 2;
blocks_per_cycle = 8l;
blocks_per_commitment = 4l;
blocks_per_roll_snapshot = 4l;
blocks_per_voting_period = 64l;
time_between_blocks =
List.map Period_repr.of_seconds_exn [ 1L ; 0L ] ;
time_between_blocks = List.map Period_repr.of_seconds_exn [1L; 0L];
proof_of_work_threshold = Int64.of_int (-1);
initial_endorsers = 1;
delay_per_missing_endorsement = Period_repr.of_seconds_exn 1L;
}
let constants_test = Constants_repr.{
let constants_test =
Constants_repr.
{
constants_mainnet with
blocks_per_cycle = 128l;
blocks_per_commitment = 4l;
blocks_per_roll_snapshot = 32l;
blocks_per_voting_period = 256l;
time_between_blocks =
List.map Period_repr.of_seconds_exn [ 1L ; 0L ] ;
time_between_blocks = List.map Period_repr.of_seconds_exn [1L; 0L];
proof_of_work_threshold = Int64.of_int (-1);
initial_endorsers = 1;
delay_per_missing_endorsement = Period_repr.of_seconds_exn 1L;
}
let bootstrap_accounts_strings = [
"edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" ;
let bootstrap_accounts_strings =
[ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav";
"edpktzNbDAUjUk697W7gYg2CRuBQjyPxbEg8dLccYYwKSKvkPvjtV9";
"edpkuTXkJDGcFd5nh6VvMz8phXxU3Bi7h6hqgywNFi1vZTfQNnS1RV";
"edpkuFrRoDSEbJYgxRtLx2ps82UdaYc1WwfS9sE11yhauZt5DgCHbU";
"edpkv8EUUH68jmo3f7Um5PezmfGrRF24gnfLpH3sVNwJnV5bVCxL2n" ;
]
"edpkv8EUUH68jmo3f7Um5PezmfGrRF24gnfLpH3sVNwJnV5bVCxL2n" ]
let boostrap_balance = Tez_repr.of_mutez_exn 4_000_000_000_000L
let bootstrap_accounts = List.map (fun s ->
let bootstrap_accounts =
List.map
(fun s ->
let public_key = Signature.Public_key.of_b58check_exn s in
let public_key_hash = Signature.Public_key.hash public_key in
Parameters_repr.{
Parameters_repr.
{
public_key_hash;
public_key = Some public_key;
amount = boostrap_balance;
@ -108,7 +114,9 @@ let bootstrap_accounts = List.map (fun s ->
(* TODO this could be generated from OCaml together with the faucet
for now these are harcoded values in the tests *)
let commitments =
let json_result = Data_encoding.Json.from_string {json|
let json_result =
Data_encoding.Json.from_string
{json|
[
[ "btz1bRL4X5BWo2Fj4EsBdUwexXqgTf75uf1qa", "23932454669343" ],
[ "btz1SxjV1syBgftgKy721czKi3arVkVwYUFSv", "72954577464032" ],
@ -123,20 +131,21 @@ let commitments =
]|json}
in
match json_result with
| Error err -> raise (Failure err)
| Ok json -> Data_encoding.Json.destruct
(Data_encoding.list Commitment_repr.encoding) json
| Error err ->
raise (Failure err)
| Ok json ->
Data_encoding.Json.destruct
(Data_encoding.list Commitment_repr.encoding)
json
let make_bootstrap_account (pkh, pk, amount) =
Parameters_repr.{public_key_hash = pkh; public_key = Some pk; amount}
let parameters_of_constants
?(bootstrap_accounts = bootstrap_accounts)
?(bootstrap_contracts = [])
?(with_commitments = false)
constants =
let parameters_of_constants ?(bootstrap_accounts = bootstrap_accounts)
?(bootstrap_contracts = []) ?(with_commitments = false) constants =
let commitments = if with_commitments then commitments else [] in
Parameters_repr.{
Parameters_repr.
{
bootstrap_accounts;
bootstrap_contracts;
commitments;

View File

@ -26,7 +26,9 @@
open Protocol
val constants_mainnet : Constants_repr.parametric
val constants_sandbox : Constants_repr.parametric
val constants_test : Constants_repr.parametric
val make_bootstrap_account :
@ -37,6 +39,7 @@ val parameters_of_constants:
?bootstrap_accounts:Parameters_repr.bootstrap_account list ->
?bootstrap_contracts:Parameters_repr.bootstrap_contract list ->
?with_commitments:bool ->
Constants_repr.parametric -> Parameters_repr.t
Constants_repr.parametric ->
Parameters_repr.t
val json_of_parameters : Parameters_repr.t -> Data_encoding.json

View File

@ -1,22 +1,22 @@
(library
(name tezos_protocol_005_PsBabyM1_parameters)
(public_name tezos-protocol-005-PsBabyM1-parameters)
(name tezos_protocol_006_PsCARTHA_parameters)
(public_name tezos-protocol-006-PsCARTHA-parameters)
(modules :standard \ gen)
(libraries tezos-base
tezos-protocol-environment
tezos-protocol-005-PsBabyM1)
tezos-protocol-006-PsCARTHA)
(flags (:standard -open Tezos_base__TzPervasives
-open Tezos_protocol_005_PsBabyM1
-open Tezos_protocol_006_PsCARTHA
-linkall))
)
(executable
(name gen)
(libraries tezos-base
tezos-protocol-005-PsBabyM1-parameters)
tezos-protocol-006-PsCARTHA-parameters)
(modules gen)
(flags (:standard -open Tezos_base__TzPervasives
-open Tezos_protocol_005_PsBabyM1_parameters
-open Tezos_protocol_006_PsCARTHA_parameters
-linkall)))
(rule

View File

@ -1,2 +1,2 @@
(lang dune 1.11)
(name tezos-protocol-005-PsBabyM1-parameters)
(name tezos-protocol-006-PsCARTHA-parameters)

View File

@ -29,18 +29,19 @@
let () =
let print_usage_and_fail s =
Printf.eprintf "Usage: %s [ --sandbox | --test | --mainnet ]"
Sys.argv.(0) ;
Printf.eprintf "Usage: %s [ --sandbox | --test | --mainnet ]" Sys.argv.(0) ;
raise (Invalid_argument s)
in
let dump parameters file =
let str = Data_encoding.Json.to_string
(Default_parameters.json_of_parameters parameters) in
let fd = open_out file in
output_string fd str ;
close_out fd
let str =
Data_encoding.Json.to_string
(Default_parameters.json_of_parameters parameters)
in
if Array.length Sys.argv < 2 then print_usage_and_fail "" else
let fd = open_out file in
output_string fd str ; close_out fd
in
if Array.length Sys.argv < 2 then print_usage_and_fail ""
else
match Sys.argv.(1) with
| "--sandbox" ->
dump
@ -48,10 +49,13 @@ let () =
"sandbox-parameters.json"
| "--test" ->
dump
Default_parameters.(parameters_of_constants ~with_commitments:true constants_sandbox)
Default_parameters.(
parameters_of_constants ~with_commitments:true constants_sandbox)
"test-parameters.json"
| "--mainnet" ->
dump
Default_parameters.(parameters_of_constants ~with_commitments:true constants_mainnet)
Default_parameters.(
parameters_of_constants ~with_commitments:true constants_mainnet)
"mainnet-parameters.json"
| s -> print_usage_and_fail s
| s ->
print_usage_and_fail s

View File

@ -8,12 +8,13 @@ license: "MIT"
depends: [
"tezos-tooling" { with-test }
"ocamlfind" { build }
"dune" { build & >= "1.7" }
"dune" { >= "1.7" }
"tezos-base"
"tezos-protocol-environment"
"tezos-protocol-005-PsBabyM1"
"tezos-protocol-006-PsCARTHA"
]
build: [
["dune" "build" "-p" name "-j" jobs]
["dune" "runtest" "-p" name "-j" jobs] {with-test}
]
synopsis: "Tezos/Protocol: parameters"

View File

@ -1,5 +1,5 @@
{
"hash": "PsBabyM1eUXZseaJdmXFApDSBqj8YBfwELoxZHHW77EMcAbbwAS",
"hash": "PsCARTHAGazKbHtnKfLzQg3kms52kSRpgnDY982a9oYsSXRLQEb",
"modules": [
"Misc",
"Storage_description",

View File

@ -24,12 +24,16 @@
(*****************************************************************************)
type t = Raw_context.t
type context = t
module type BASIC_DATA = sig
type t
include Compare.S with type t := t
val encoding : t Data_encoding.t
val pp : Format.formatter -> t -> unit
end
@ -38,60 +42,76 @@ module Period = Period_repr
module Timestamp = struct
include Time_repr
let current = Raw_context.current_timestamp
end
include Operation_repr
module Operation = struct
type 'kind t = 'kind operation = {
shell : Operation.shell_header;
protocol_data : 'kind protocol_data;
}
type packed = packed_operation
let unsigned_encoding = unsigned_operation_encoding
include Operation_repr
end
module Block_header = Block_header_repr
module Vote = struct
include Vote_repr
include Vote_storage
end
module Raw_level = Raw_level_repr
module Cycle = Cycle_repr
module Script_int = Script_int_repr
module Script_timestamp = struct
include Script_timestamp_repr
let now ctxt =
let { Constants_repr.time_between_blocks ; _ } =
Raw_context.constants ctxt in
let {Constants_repr.time_between_blocks; _} = Raw_context.constants ctxt in
match time_between_blocks with
| [] -> failwith "Internal error: 'time_between_block' constants \
is an empty list."
| [] ->
failwith
"Internal error: 'time_between_block' constants is an empty list."
| first_delay :: _ ->
let current_timestamp = Raw_context.predecessor_timestamp ctxt in
Time.add current_timestamp (Period_repr.to_seconds first_delay)
|> Timestamp.to_seconds
|> of_int64
|> Timestamp.to_seconds |> of_int64
end
module Script = struct
include Michelson_v1_primitives
include Script_repr
let force_decode ctxt lexpr =
Lwt.return
(Script_repr.force_decode lexpr >>? fun (v, cost) ->
Raw_context.consume_gas ctxt cost >|? fun ctxt ->
(v, ctxt))
( Script_repr.force_decode lexpr
>>? fun (v, cost) ->
Raw_context.consume_gas ctxt cost >|? fun ctxt -> (v, ctxt) )
let force_bytes ctxt lexpr =
Lwt.return
(Script_repr.force_bytes lexpr >>? fun (b, cost) ->
Raw_context.consume_gas ctxt cost >|? fun ctxt ->
(b, ctxt))
( Script_repr.force_bytes lexpr
>>? fun (b, cost) ->
Raw_context.consume_gas ctxt cost >|? fun ctxt -> (b, ctxt) )
module Legacy_support = Legacy_script_support_repr
end
module Fees = Fees_storage
type public_key = Signature.Public_key.t
type public_key_hash = Signature.Public_key_hash.t
type signature = Signature.t
module Constants = struct
@ -103,66 +123,95 @@ module Voting_period = Voting_period_repr
module Gas = struct
include Gas_limit_repr
type error += Gas_limit_too_high = Raw_context.Gas_limit_too_high
let check_limit = Raw_context.check_gas_limit
let set_limit = Raw_context.set_gas_limit
let set_unlimited = Raw_context.set_gas_unlimited
let consume = Raw_context.consume_gas
let check_enough = Raw_context.check_enough_gas
let level = Raw_context.gas_level
let consumed = Raw_context.gas_consumed
let block_level = Raw_context.block_gas_level
end
module Level = struct
include Level_repr
include Level_storage
end
module Contract = struct
include Contract_repr
include Contract_storage
let originate c contract ~balance ~script ~delegate =
originate c contract ~balance ~script ~delegate
let init_origination_nonce = Raw_context.init_origination_nonce
let unset_origination_nonce = Raw_context.unset_origination_nonce
end
module Big_map = struct
type id = Z.t
let fresh = Storage.Big_map.Next.incr
let fresh_temporary = Raw_context.fresh_temporary_big_map
let mem c m k = Storage.Big_map.Contents.mem (c, m) k
let get_opt c m k = Storage.Big_map.Contents.get_option (c, m) k
let rpc_arg = Storage.Big_map.rpc_arg
let cleanup_temporary c =
Raw_context.temporary_big_maps c Storage.Big_map.remove_rec c >>= fun c ->
Lwt.return (Raw_context.reset_temporary_big_map c)
Raw_context.temporary_big_maps c Storage.Big_map.remove_rec c
>>= fun c -> Lwt.return (Raw_context.reset_temporary_big_map c)
let exists c id =
Lwt.return (Raw_context.consume_gas c (Gas_limit_repr.read_bytes_cost Z.zero)) >>=? fun c ->
Storage.Big_map.Key_type.get_option c id >>=? fun kt ->
Lwt.return
(Raw_context.consume_gas c (Gas_limit_repr.read_bytes_cost Z.zero))
>>=? fun c ->
Storage.Big_map.Key_type.get_option c id
>>=? fun kt ->
match kt with
| None -> return (c, None)
| None ->
return (c, None)
| Some kt ->
Storage.Big_map.Value_type.get c id >>=? fun kv ->
return (c, Some (kt, kv))
Storage.Big_map.Value_type.get c id
>>=? fun kv -> return (c, Some (kt, kv))
end
module Delegate = Delegate_storage
module Roll = struct
include Roll_repr
include Roll_storage
end
module Nonce = Nonce_storage
module Seed = struct
include Seed_repr
include Seed_storage
end
module Fitness = struct
include Fitness_repr
include Fitness
type fitness = t
include Fitness_storage
type fitness = t
include Fitness_storage
end
module Bootstrap = Bootstrap_storage
@ -174,39 +223,57 @@ end
module Global = struct
let get_block_priority = Storage.Block_priority.get
let set_block_priority = Storage.Block_priority.set
end
let prepare_first_block = Init_storage.prepare_first_block
let prepare = Init_storage.prepare
let finalize ?commit_message:message c =
let fitness = Fitness.from_int64 (Fitness.current c) in
let context = Raw_context.recover c in
{ Updater.context ; fitness ; message ; max_operations_ttl = 60 ;
{
Updater.context;
fitness;
message;
max_operations_ttl = 60;
last_allowed_fork_level =
Raw_level.to_int32 @@ Level.last_allowed_fork_level c;
}
let activate = Raw_context.activate
let fork_test_chain = Raw_context.fork_test_chain
let record_endorsement = Raw_context.record_endorsement
let allowed_endorsements = Raw_context.allowed_endorsements
let init_endorsements = Raw_context.init_endorsements
let included_endorsements = Raw_context.included_endorsements
let reset_internal_nonce = Raw_context.reset_internal_nonce
let fresh_internal_nonce = Raw_context.fresh_internal_nonce
let record_internal_nonce = Raw_context.record_internal_nonce
let internal_nonce_already_recorded = Raw_context.internal_nonce_already_recorded
let internal_nonce_already_recorded =
Raw_context.internal_nonce_already_recorded
let add_deposit = Raw_context.add_deposit
let add_fees = Raw_context.add_fees
let add_rewards = Raw_context.add_rewards
let get_deposits = Raw_context.get_deposits
let get_fees = Raw_context.get_fees
let get_rewards = Raw_context.get_rewards
let description = Raw_context.description

File diff suppressed because it is too large Load Diff

View File

@ -28,9 +28,7 @@ open Alpha_context
let custom_root = RPC_path.open_root
module Seed = struct
module S = struct
open Data_encoding
let seed =
@ -40,74 +38,66 @@ module Seed = struct
~input:empty
~output:Seed.seed_encoding
RPC_path.(custom_root / "context" / "seed")
end
let () =
let open Services_registration in
register0 S.seed begin fun ctxt () () ->
register0 S.seed (fun ctxt () () ->
let l = Level.current ctxt in
Seed.for_cycle ctxt l.cycle
end
let get ctxt block =
RPC_context.make_call0 S.seed ctxt block () ()
Seed.for_cycle ctxt l.cycle)
let get ctxt block = RPC_context.make_call0 S.seed ctxt block () ()
end
module Nonce = struct
type info =
| Revealed of Nonce.t
| Missing of Nonce_hash.t
| Forgotten
type info = Revealed of Nonce.t | Missing of Nonce_hash.t | Forgotten
let info_encoding =
let open Data_encoding in
union [
case (Tag 0)
union
[ case
(Tag 0)
~title:"Revealed"
(obj1 (req "nonce" Nonce.encoding))
(function Revealed nonce -> Some nonce | _ -> None)
(fun nonce -> Revealed nonce);
case (Tag 1)
case
(Tag 1)
~title:"Missing"
(obj1 (req "hash" Nonce_hash.encoding))
(function Missing nonce -> Some nonce | _ -> None)
(fun nonce -> Missing nonce);
case (Tag 2)
case
(Tag 2)
~title:"Forgotten"
empty
(function Forgotten -> Some () | _ -> None)
(fun () -> Forgotten) ;
]
(fun () -> Forgotten) ]
module S = struct
let get =
RPC_service.get_service
~description:"Info about the nonce of a previous block."
~query:RPC_query.empty
~output:info_encoding
RPC_path.(custom_root / "context" / "nonces" /: Raw_level.rpc_arg)
end
let register () =
let open Services_registration in
register1 S.get begin fun ctxt raw_level () () ->
register1 S.get (fun ctxt raw_level () () ->
let level = Level.from_raw ctxt raw_level in
Nonce.get ctxt level >>= function
| Ok (Revealed nonce) -> return (Revealed nonce)
Nonce.get ctxt level
>>= function
| Ok (Revealed nonce) ->
return (Revealed nonce)
| Ok (Unrevealed {nonce_hash; _}) ->
return (Missing nonce_hash)
| Error _ -> return Forgotten
end
| Error _ ->
return Forgotten)
let get ctxt block level =
RPC_context.make_call1 S.get ctxt block level () ()
end
module Contract = Contract_services

View File

@ -26,22 +26,14 @@
open Alpha_context
module Seed : sig
val get : 'a #RPC_context.simple -> 'a -> Seed.seed shell_tzresult Lwt.t
end
module Nonce : sig
type info =
| Revealed of Nonce.t
| Missing of Nonce_hash.t
| Forgotten
type info = Revealed of Nonce.t | Missing of Nonce_hash.t | Forgotten
val get :
'a #RPC_context.simple ->
'a -> Raw_level.t -> info shell_tzresult Lwt.t
'a #RPC_context.simple -> 'a -> Raw_level.t -> info shell_tzresult Lwt.t
end
module Contract = Contract_services

View File

@ -29,29 +29,32 @@ open Alpha_context
Returns None in case of a tie, if proposal quorum is below required
minimum or if there are no proposals. *)
let select_winning_proposal ctxt =
Vote.get_proposals ctxt >>=? fun proposals ->
Vote.get_proposals ctxt
>>=? fun proposals ->
let merge proposal vote winners =
match winners with
| None -> Some ([proposal], vote)
| None ->
Some ([proposal], vote)
| Some (winners, winners_vote) as previous ->
if Compare.Int32.(vote = winners_vote) then
Some (proposal :: winners, winners_vote)
else if Compare.Int32.(vote > winners_vote) then
Some ([proposal], vote)
else
previous in
else if Compare.Int32.(vote > winners_vote) then Some ([proposal], vote)
else previous
in
match Protocol_hash.Map.fold merge proposals None with
| Some ([proposal], vote) ->
Vote.listing_size ctxt >>=? fun max_vote ->
Vote.listing_size ctxt
>>=? fun max_vote ->
let min_proposal_quorum = Constants.min_proposal_quorum ctxt in
let min_vote_to_pass =
Int32.div (Int32.mul min_proposal_quorum max_vote) 100_00l in
if Compare.Int32.(vote >= min_vote_to_pass) then
return_some proposal
else
return_none
Int32.div (Int32.mul min_proposal_quorum max_vote) 100_00l
in
if Compare.Int32.(vote >= min_vote_to_pass) then return_some proposal
else return_none
| _ ->
return_none (* in case of a tie, let's do nothing. *)
return_none
(* in case of a tie, let's do nothing. *)
(** A proposal is approved if it has supermajority and the participation reaches
the current quorum.
@ -63,10 +66,14 @@ let select_winning_proposal ctxt =
The expected quorum is calculated using the last participation EMA, capped
by the min/max quorum protocol constants. *)
let check_approval_and_update_participation_ema ctxt =
Vote.get_ballots ctxt >>=? fun ballots ->
Vote.listing_size ctxt >>=? fun maximum_vote ->
Vote.get_participation_ema ctxt >>=? fun participation_ema ->
Vote.get_current_quorum ctxt >>=? fun expected_quorum ->
Vote.get_ballots ctxt
>>=? fun ballots ->
Vote.listing_size ctxt
>>=? fun maximum_vote ->
Vote.get_participation_ema ctxt
>>=? fun participation_ema ->
Vote.get_current_quorum ctxt
>>=? fun expected_quorum ->
(* Note overflows: considering a maximum of 8e8 tokens, with roll size as
small as 1e3, there is a maximum of 8e5 rolls and thus votes.
In 'participation' an Int64 is used because in the worst case 'all_votes is
@ -75,80 +82,96 @@ let check_approval_and_update_participation_ema ctxt =
let casted_votes = Int32.add ballots.yay ballots.nay in
let all_votes = Int32.add casted_votes ballots.pass in
let supermajority = Int32.div (Int32.mul 8l casted_votes) 10l in
let participation = (* in centile of percentage *)
Int64.(to_int32
(div
(mul (of_int32 all_votes) 100_00L)
(of_int32 maximum_vote))) in
let outcome = Compare.Int32.(participation >= expected_quorum &&
ballots.yay >= supermajority) in
let participation =
(* in centile of percentage *)
Int64.(
to_int32 (div (mul (of_int32 all_votes) 100_00L) (of_int32 maximum_vote)))
in
let outcome =
Compare.Int32.(
participation >= expected_quorum && ballots.yay >= supermajority)
in
let new_participation_ema =
Int32.(div (add
(mul 8l participation_ema)
(mul 2l participation))
10l) in
Vote.set_participation_ema ctxt new_participation_ema >>=? fun ctxt ->
return (ctxt, outcome)
Int32.(div (add (mul 8l participation_ema) (mul 2l participation)) 10l)
in
Vote.set_participation_ema ctxt new_participation_ema
>>=? fun ctxt -> return (ctxt, outcome)
(** Implements the state machine of the amendment procedure.
Note that [freeze_listings], that computes the vote weight of each delegate,
is run at the beginning of each voting period.
*)
let start_new_voting_period ctxt =
Vote.get_current_period_kind ctxt >>=? function
| Proposal -> begin
select_winning_proposal ctxt >>=? fun proposal ->
Vote.clear_proposals ctxt >>= fun ctxt ->
Vote.clear_listings ctxt >>=? fun ctxt ->
Vote.get_current_period_kind ctxt
>>=? function
| Proposal -> (
select_winning_proposal ctxt
>>=? fun proposal ->
Vote.clear_proposals ctxt
>>= fun ctxt ->
Vote.clear_listings ctxt
>>=? fun ctxt ->
match proposal with
| None ->
Vote.freeze_listings ctxt >>=? fun ctxt ->
return ctxt
Vote.freeze_listings ctxt >>=? fun ctxt -> return ctxt
| Some proposal ->
Vote.init_current_proposal ctxt proposal >>=? fun ctxt ->
Vote.freeze_listings ctxt >>=? fun ctxt ->
Vote.set_current_period_kind ctxt Testing_vote >>=? fun ctxt ->
return ctxt
end
Vote.init_current_proposal ctxt proposal
>>=? fun ctxt ->
Vote.freeze_listings ctxt
>>=? fun ctxt ->
Vote.set_current_period_kind ctxt Testing_vote
>>=? fun ctxt -> return ctxt )
| Testing_vote ->
check_approval_and_update_participation_ema ctxt >>=? fun (ctxt, approved) ->
Vote.clear_ballots ctxt >>= fun ctxt ->
Vote.clear_listings ctxt >>=? fun ctxt ->
check_approval_and_update_participation_ema ctxt
>>=? fun (ctxt, approved) ->
Vote.clear_ballots ctxt
>>= fun ctxt ->
Vote.clear_listings ctxt
>>=? fun ctxt ->
if approved then
let expiration = (* in two days maximum... *)
Time.add (Timestamp.current ctxt) (Constants.test_chain_duration ctxt) in
Vote.get_current_proposal ctxt >>=? fun proposal ->
fork_test_chain ctxt proposal expiration >>= fun ctxt ->
Vote.set_current_period_kind ctxt Testing >>=? fun ctxt ->
return ctxt
let expiration =
(* in two days maximum... *)
Time.add
(Timestamp.current ctxt)
(Constants.test_chain_duration ctxt)
in
Vote.get_current_proposal ctxt
>>=? fun proposal ->
fork_test_chain ctxt proposal expiration
>>= fun ctxt ->
Vote.set_current_period_kind ctxt Testing >>=? fun ctxt -> return ctxt
else
Vote.clear_current_proposal ctxt >>=? fun ctxt ->
Vote.freeze_listings ctxt >>=? fun ctxt ->
Vote.set_current_period_kind ctxt Proposal >>=? fun ctxt ->
return ctxt
Vote.clear_current_proposal ctxt
>>=? fun ctxt ->
Vote.freeze_listings ctxt
>>=? fun ctxt ->
Vote.set_current_period_kind ctxt Proposal >>=? fun ctxt -> return ctxt
| Testing ->
Vote.freeze_listings ctxt >>=? fun ctxt ->
Vote.set_current_period_kind ctxt Promotion_vote >>=? fun ctxt ->
return ctxt
Vote.freeze_listings ctxt
>>=? fun ctxt ->
Vote.set_current_period_kind ctxt Promotion_vote
>>=? fun ctxt -> return ctxt
| Promotion_vote ->
check_approval_and_update_participation_ema ctxt >>=? fun (ctxt, approved) ->
begin
if approved then
Vote.get_current_proposal ctxt >>=? fun proposal ->
activate ctxt proposal >>= fun ctxt ->
return ctxt
else
return ctxt
end >>=? fun ctxt ->
Vote.clear_ballots ctxt >>= fun ctxt ->
Vote.clear_listings ctxt >>=? fun ctxt ->
Vote.clear_current_proposal ctxt >>=? fun ctxt ->
Vote.freeze_listings ctxt >>=? fun ctxt ->
Vote.set_current_period_kind ctxt Proposal >>=? fun ctxt ->
return ctxt
check_approval_and_update_participation_ema ctxt
>>=? fun (ctxt, approved) ->
( if approved then
Vote.get_current_proposal ctxt
>>=? fun proposal -> activate ctxt proposal >>= fun ctxt -> return ctxt
else return ctxt )
>>=? fun ctxt ->
Vote.clear_ballots ctxt
>>= fun ctxt ->
Vote.clear_listings ctxt
>>=? fun ctxt ->
Vote.clear_current_proposal ctxt
>>=? fun ctxt ->
Vote.freeze_listings ctxt
>>=? fun ctxt ->
Vote.set_current_period_kind ctxt Proposal >>=? fun ctxt -> return ctxt
type error += (* `Branch *)
| Invalid_proposal
type error +=
| (* `Branch *)
Invalid_proposal
| Unexpected_proposal
| Unauthorized_proposal
| Too_many_proposals
@ -183,7 +206,8 @@ let () =
`Branch
~id:"unauthorized_proposal"
~title:"Unauthorized proposal"
~description:"The delegate provided for the proposal is not in the voting listings."
~description:
"The delegate provided for the proposal is not in the voting listings."
~pp:(fun ppf () -> Format.fprintf ppf "Unauthorized proposal")
empty
(function Unauthorized_proposal -> Some () | _ -> None)
@ -203,7 +227,8 @@ let () =
`Branch
~id:"unauthorized_ballot"
~title:"Unauthorized ballot"
~description:"The delegate provided for the ballot is not in the voting listings."
~description:
"The delegate provided for the ballot is not in the voting listings."
~pp:(fun ppf () -> Format.fprintf ppf "Unauthorized ballot")
empty
(function Unauthorized_ballot -> Some () | _ -> None)
@ -213,7 +238,8 @@ let () =
`Branch
~id:"too_many_proposals"
~title:"Too many proposals"
~description:"The delegate reached the maximum number of allowed proposals."
~description:
"The delegate reached the maximum number of allowed proposals."
~pp:(fun ppf () -> Format.fprintf ppf "Too many proposals")
empty
(function Too_many_proposals -> Some () | _ -> None)
@ -231,60 +257,67 @@ let () =
(* @return [true] if [List.length l] > [n] w/o computing length *)
let rec longer_than l n =
if Compare.Int.(n < 0) then assert false else
if Compare.Int.(n < 0) then assert false
else
match l with
| [] -> false
| [] ->
false
| _ :: rest ->
if Compare.Int.(n = 0) then true
else (* n > 0 *)
longer_than rest (n - 1)
let record_proposals ctxt delegate proposals =
begin match proposals with
| [] -> fail Empty_proposal
| _ :: _ -> return_unit
end >>=? fun () ->
Vote.get_current_period_kind ctxt >>=? function
(match proposals with [] -> fail Empty_proposal | _ :: _ -> return_unit)
>>=? fun () ->
Vote.get_current_period_kind ctxt
>>=? function
| Proposal ->
Vote.in_listings ctxt delegate >>= fun in_listings ->
Vote.in_listings ctxt delegate
>>= fun in_listings ->
if in_listings then
Vote.recorded_proposal_count_for_delegate ctxt delegate >>=? fun count ->
Vote.recorded_proposal_count_for_delegate ctxt delegate
>>=? fun count ->
fail_when
(longer_than proposals (Constants.max_proposals_per_delegate - count))
Too_many_proposals >>=? fun () ->
Too_many_proposals
>>=? fun () ->
fold_left_s
(fun ctxt proposal ->
Vote.record_proposal ctxt proposal delegate)
ctxt proposals >>=? fun ctxt ->
return ctxt
else
fail Unauthorized_proposal
(fun ctxt proposal -> Vote.record_proposal ctxt proposal delegate)
ctxt
proposals
>>=? fun ctxt -> return ctxt
else fail Unauthorized_proposal
| Testing_vote | Testing | Promotion_vote ->
fail Unexpected_proposal
let record_ballot ctxt delegate proposal ballot =
Vote.get_current_period_kind ctxt >>=? function
Vote.get_current_period_kind ctxt
>>=? function
| Testing_vote | Promotion_vote ->
Vote.get_current_proposal ctxt >>=? fun current_proposal ->
fail_unless (Protocol_hash.equal proposal current_proposal)
Invalid_proposal >>=? fun () ->
Vote.has_recorded_ballot ctxt delegate >>= fun has_ballot ->
fail_when has_ballot Unauthorized_ballot >>=? fun () ->
Vote.in_listings ctxt delegate >>= fun in_listings ->
if in_listings then
Vote.record_ballot ctxt delegate ballot
else
fail Unauthorized_ballot
Vote.get_current_proposal ctxt
>>=? fun current_proposal ->
fail_unless
(Protocol_hash.equal proposal current_proposal)
Invalid_proposal
>>=? fun () ->
Vote.has_recorded_ballot ctxt delegate
>>= fun has_ballot ->
fail_when has_ballot Unauthorized_ballot
>>=? fun () ->
Vote.in_listings ctxt delegate
>>= fun in_listings ->
if in_listings then Vote.record_ballot ctxt delegate ballot
else fail Unauthorized_ballot
| Testing | Proposal ->
fail Unexpected_ballot
let last_of_a_voting_period ctxt l =
Compare.Int32.(Int32.succ l.Level.voting_period_position =
Constants.blocks_per_voting_period ctxt )
Compare.Int32.(
Int32.succ l.Level.voting_period_position
= Constants.blocks_per_voting_period ctxt)
let may_start_new_voting_period ctxt =
let level = Level.current ctxt in
if last_of_a_voting_period ctxt level then
start_new_voting_period ctxt
else
return ctxt
if last_of_a_voting_period ctxt level then start_new_voting_period ctxt
else return ctxt

View File

@ -51,8 +51,7 @@ open Alpha_context
(** If at the end of a voting period, moves to the next one following
the state machine of the amendment procedure. *)
val may_start_new_voting_period:
context -> context tzresult Lwt.t
val may_start_new_voting_period : context -> context tzresult Lwt.t
type error +=
| Unexpected_proposal
@ -64,16 +63,13 @@ type error +=
@raise Unexpected_proposal if [ctxt] is not in a proposal period.
@raise Unauthorized_proposal if [delegate] is not in the listing. *)
val record_proposals :
context ->
public_key_hash -> Protocol_hash.t list ->
context tzresult Lwt.t
context -> public_key_hash -> Protocol_hash.t list -> context tzresult Lwt.t
type error +=
| Invalid_proposal
| Unexpected_ballot
| Unauthorized_ballot
type error += Invalid_proposal | Unexpected_ballot | Unauthorized_ballot
val record_ballot :
context ->
public_key_hash -> Protocol_hash.t -> Vote.ballot ->
public_key_hash ->
Protocol_hash.t ->
Vote.ballot ->
context tzresult Lwt.t

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -31,9 +31,7 @@
open Alpha_context
(** Result of applying a {!Operation.t}. Follows the same structure. *)
type 'kind operation_metadata = {
contents: 'kind contents_result_list ;
}
type 'kind operation_metadata = {contents : 'kind contents_result_list}
and packed_operation_metadata =
| Operation_metadata : 'kind operation_metadata -> packed_operation_metadata
@ -43,34 +41,43 @@ and packed_operation_metadata =
and 'kind contents_result_list =
| Single_result : 'kind contents_result -> 'kind contents_result_list
| Cons_result :
'kind Kind.manager contents_result * 'rest Kind.manager contents_result_list ->
(('kind * 'rest) Kind.manager ) contents_result_list
'kind Kind.manager contents_result
* 'rest Kind.manager contents_result_list
-> ('kind * 'rest) Kind.manager contents_result_list
and packed_contents_result_list =
| Contents_result_list : 'kind contents_result_list -> packed_contents_result_list
| Contents_result_list :
'kind contents_result_list
-> packed_contents_result_list
(** Result of applying an {!Operation.contents}. Follows the same structure. *)
and 'kind contents_result =
| Endorsement_result :
{ balance_updates : Delegate.balance_updates ;
| Endorsement_result : {
balance_updates : Delegate.balance_updates;
delegate : Signature.Public_key_hash.t;
slots : int list;
} -> Kind.endorsement contents_result
}
-> Kind.endorsement contents_result
| Seed_nonce_revelation_result :
Delegate.balance_updates -> Kind.seed_nonce_revelation contents_result
Delegate.balance_updates
-> Kind.seed_nonce_revelation contents_result
| Double_endorsement_evidence_result :
Delegate.balance_updates -> Kind.double_endorsement_evidence contents_result
Delegate.balance_updates
-> Kind.double_endorsement_evidence contents_result
| Double_baking_evidence_result :
Delegate.balance_updates -> Kind.double_baking_evidence contents_result
Delegate.balance_updates
-> Kind.double_baking_evidence contents_result
| Activate_account_result :
Delegate.balance_updates -> Kind.activate_account contents_result
Delegate.balance_updates
-> Kind.activate_account contents_result
| Proposals_result : Kind.proposals contents_result
| Ballot_result : Kind.ballot contents_result
| Manager_operation_result :
{ balance_updates : Delegate.balance_updates ;
| Manager_operation_result : {
balance_updates : Delegate.balance_updates;
operation_result : 'kind manager_operation_result;
internal_operation_results : packed_internal_operation_result list;
} -> 'kind Kind.manager contents_result
}
-> 'kind Kind.manager contents_result
and packed_contents_result =
| Contents_result : 'kind contents_result -> packed_contents_result
@ -79,18 +86,20 @@ and packed_contents_result =
always be at the tail, and after a single [Failed]. *)
and 'kind manager_operation_result =
| Applied of 'kind successful_manager_operation_result
| Backtracked of 'kind successful_manager_operation_result * error list option
| Backtracked of
'kind successful_manager_operation_result * error list option
| Failed : 'kind Kind.manager * error list -> 'kind manager_operation_result
| Skipped : 'kind Kind.manager -> 'kind manager_operation_result
(** Result of applying a {!manager_operation_content}, either internal
or external. *)
and _ successful_manager_operation_result =
| Reveal_result :
{ consumed_gas : Z.t
} -> Kind.reveal successful_manager_operation_result
| Transaction_result :
{ storage : Script.expr option ;
| Reveal_result : {
consumed_gas : Z.t;
}
-> Kind.reveal successful_manager_operation_result
| Transaction_result : {
storage : Script.expr option;
big_map_diff : Contract.big_map_diff option;
balance_updates : Delegate.balance_updates;
originated_contracts : Contract.t list;
@ -98,63 +107,75 @@ and _ successful_manager_operation_result =
storage_size : Z.t;
paid_storage_size_diff : Z.t;
allocated_destination_contract : bool;
} -> Kind.transaction successful_manager_operation_result
| Origination_result :
{ big_map_diff : Contract.big_map_diff option ;
}
-> Kind.transaction successful_manager_operation_result
| Origination_result : {
big_map_diff : Contract.big_map_diff option;
balance_updates : Delegate.balance_updates;
originated_contracts : Contract.t list;
consumed_gas : Z.t;
storage_size : Z.t;
paid_storage_size_diff : Z.t;
} -> Kind.origination successful_manager_operation_result
| Delegation_result :
{ consumed_gas : Z.t
} -> Kind.delegation successful_manager_operation_result
}
-> Kind.origination successful_manager_operation_result
| Delegation_result : {
consumed_gas : Z.t;
}
-> Kind.delegation successful_manager_operation_result
and packed_successful_manager_operation_result =
| Successful_manager_result :
'kind successful_manager_operation_result -> packed_successful_manager_operation_result
'kind successful_manager_operation_result
-> packed_successful_manager_operation_result
and packed_internal_operation_result =
| Internal_operation_result :
'kind internal_operation * 'kind manager_operation_result ->
packed_internal_operation_result
'kind internal_operation * 'kind manager_operation_result
-> packed_internal_operation_result
(** Serializer for {!packed_operation_result}. *)
val operation_metadata_encoding : packed_operation_metadata Data_encoding.t
val operation_data_and_metadata_encoding
: (Operation.packed_protocol_data * packed_operation_metadata) Data_encoding.t
val operation_data_and_metadata_encoding :
(Operation.packed_protocol_data * packed_operation_metadata) Data_encoding.t
type 'kind contents_and_result_list =
| Single_and_result : 'kind Alpha_context.contents * 'kind contents_result -> 'kind contents_and_result_list
| Cons_and_result : 'kind Kind.manager Alpha_context.contents * 'kind Kind.manager contents_result * 'rest Kind.manager contents_and_result_list -> ('kind * 'rest) Kind.manager contents_and_result_list
| Single_and_result :
'kind Alpha_context.contents * 'kind contents_result
-> 'kind contents_and_result_list
| Cons_and_result :
'kind Kind.manager Alpha_context.contents
* 'kind Kind.manager contents_result
* 'rest Kind.manager contents_and_result_list
-> ('kind * 'rest) Kind.manager contents_and_result_list
type packed_contents_and_result_list =
| Contents_and_result_list : 'kind contents_and_result_list -> packed_contents_and_result_list
| Contents_and_result_list :
'kind contents_and_result_list
-> packed_contents_and_result_list
val contents_and_result_list_encoding :
packed_contents_and_result_list Data_encoding.t
val pack_contents_list :
'kind contents_list -> 'kind contents_result_list ->
'kind contents_list ->
'kind contents_result_list ->
'kind contents_and_result_list
val unpack_contents_list :
'kind contents_and_result_list ->
'kind contents_list * 'kind contents_result_list
val to_list :
packed_contents_result_list -> packed_contents_result list
val to_list : packed_contents_result_list -> packed_contents_result list
val of_list :
packed_contents_result list -> packed_contents_result_list
val of_list : packed_contents_result list -> packed_contents_result_list
type ('a, 'b) eq = Eq : ('a, 'a) eq
val kind_equal_list :
'kind contents_list -> 'kind2 contents_result_list -> ('kind, 'kind2) eq option
'kind contents_list ->
'kind2 contents_result_list ->
('kind, 'kind2) eq option
type block_metadata = {
baker : Signature.Public_key_hash.t;
@ -165,4 +186,5 @@ type block_metadata = {
deactivated : Signature.Public_key_hash.t list;
balance_updates : Delegate.balance_updates;
}
val block_metadata_encoding : block_metadata Data_encoding.encoding

View File

@ -23,15 +23,24 @@
(* *)
(*****************************************************************************)
open Alpha_context
open Misc
type error += Invalid_fitness_gap of int64 * int64 (* `Permanent *)
type error += Timestamp_too_early of Timestamp.t * Timestamp.t (* `Permanent *)
type error += Timestamp_too_early of Timestamp.t * Timestamp.t
(* `Permanent *)
type error += Unexpected_endorsement (* `Permanent *)
type error += Invalid_block_signature of Block_hash.t * Signature.Public_key_hash.t (* `Permanent *)
type error +=
| Invalid_block_signature of Block_hash.t * Signature.Public_key_hash.t
(* `Permanent *)
type error += Invalid_signature (* `Permanent *)
type error += Invalid_stamp (* `Permanent *)
let () =
@ -39,14 +48,19 @@ let () =
`Permanent
~id:"baking.timestamp_too_early"
~title:"Block forged too early"
~description:"The block timestamp is before the first slot \
for this baker at this level"
~description:
"The block timestamp is before the first slot for this baker at this \
level"
~pp:(fun ppf (r, p) ->
Format.fprintf ppf "Block forged too early (%a is before %a)"
Time.pp_hum p Time.pp_hum r)
Data_encoding.(obj2
(req "minimum" Time.encoding)
(req "provided" Time.encoding))
Format.fprintf
ppf
"Block forged too early (%a is before %a)"
Time.pp_hum
p
Time.pp_hum
r)
Data_encoding.(
obj2 (req "minimum" Time.encoding) (req "provided" Time.encoding))
(function Timestamp_too_early (r, p) -> Some (r, p) | _ -> None)
(fun (r, p) -> Timestamp_too_early (r, p)) ;
register_error_kind
@ -55,35 +69,36 @@ let () =
~title:"Invalid fitness gap"
~description:"The gap of fitness is out of bounds"
~pp:(fun ppf (m, g) ->
Format.fprintf ppf
"The gap of fitness %Ld is not between 0 and %Ld" g m)
Data_encoding.(obj2
(req "maximum" int64)
(req "provided" int64))
Format.fprintf ppf "The gap of fitness %Ld is not between 0 and %Ld" g m)
Data_encoding.(obj2 (req "maximum" int64) (req "provided" int64))
(function Invalid_fitness_gap (m, g) -> Some (m, g) | _ -> None)
(fun (m, g) -> Invalid_fitness_gap (m, g)) ;
register_error_kind
`Permanent
~id:"baking.invalid_block_signature"
~title:"Invalid block signature"
~description:
"A block was not signed with the expected private key."
~description:"A block was not signed with the expected private key."
~pp:(fun ppf (block, pkh) ->
Format.fprintf ppf "Invalid signature for block %a. Expected: %a."
Block_hash.pp_short block
Signature.Public_key_hash.pp_short pkh)
Data_encoding.(obj2
Format.fprintf
ppf
"Invalid signature for block %a. Expected: %a."
Block_hash.pp_short
block
Signature.Public_key_hash.pp_short
pkh)
Data_encoding.(
obj2
(req "block" Block_hash.encoding)
(req "expected" Signature.Public_key_hash.encoding))
(function Invalid_block_signature (block, pkh) -> Some (block, pkh) | _ -> None)
(function
| Invalid_block_signature (block, pkh) -> Some (block, pkh) | _ -> None)
(fun (block, pkh) -> Invalid_block_signature (block, pkh)) ;
register_error_kind
`Permanent
~id:"baking.invalid_signature"
~title:"Invalid block signature"
~description:"The block's signature is invalid"
~pp:(fun ppf () ->
Format.fprintf ppf "Invalid block signature")
~pp:(fun ppf () -> Format.fprintf ppf "Invalid block signature")
Data_encoding.empty
(function Invalid_signature -> Some () | _ -> None)
(fun () -> Invalid_signature) ;
@ -92,8 +107,7 @@ let () =
~id:"baking.insufficient_proof_of_work"
~title:"Insufficient block proof-of-work stamp"
~description:"The block's proof-of-work stamp is insufficient"
~pp:(fun ppf () ->
Format.fprintf ppf "Insufficient proof-of-work stamp")
~pp:(fun ppf () -> Format.fprintf ppf "Insufficient proof-of-work stamp")
Data_encoding.empty
(function Invalid_stamp -> Some () | _ -> None)
(fun () -> Invalid_stamp) ;
@ -101,9 +115,11 @@ let () =
`Permanent
~id:"baking.unexpected_endorsement"
~title:"Endorsement from unexpected delegate"
~description:"The operation is signed by a delegate without endorsement rights."
~description:
"The operation is signed by a delegate without endorsement rights."
~pp:(fun ppf () ->
Format.fprintf ppf
Format.fprintf
ppf
"The endorsement is signed by a delegate without endorsement rights.")
Data_encoding.unit
(function Unexpected_endorsement -> Some () | _ -> None)
@ -112,20 +128,24 @@ let () =
let minimal_time c priority pred_timestamp =
let priority = Int32.of_int priority in
let rec cumsum_time_between_blocks acc durations p =
if Compare.Int32.(<=) p 0l then
ok acc
else match durations with
| [] -> cumsum_time_between_blocks acc [ Period.one_minute ] p
if Compare.Int32.( <= ) p 0l then ok acc
else
match durations with
| [] ->
cumsum_time_between_blocks acc [Period.one_minute] p
| [last] ->
Period.mult p last >>? fun period ->
Timestamp.(acc +? period)
Period.mult p last >>? fun period -> Timestamp.(acc +? period)
| first :: durations ->
Timestamp.(acc +? first) >>? fun acc ->
Timestamp.(acc +? first)
>>? fun acc ->
let p = Int32.pred p in
cumsum_time_between_blocks acc durations p in
cumsum_time_between_blocks acc durations p
in
Lwt.return
(cumsum_time_between_blocks
pred_timestamp (Constants.time_between_blocks c) (Int32.succ priority))
pred_timestamp
(Constants.time_between_blocks c)
(Int32.succ priority))
let earlier_predecessor_timestamp ctxt level =
let current = Level.current ctxt in
@ -135,25 +155,29 @@ let earlier_predecessor_timestamp ctxt level =
if Compare.Int32.(gap < 1l) then
failwith "Baking.earlier_block_timestamp: past block."
else
Lwt.return (Period.mult (Int32.pred gap) step) >>=? fun delay ->
Lwt.return Timestamp.(current_timestamp +? delay) >>=? fun result ->
return result
Lwt.return (Period.mult (Int32.pred gap) step)
>>=? fun delay ->
Lwt.return Timestamp.(current_timestamp +? delay)
>>=? fun result -> return result
let check_timestamp c priority pred_timestamp =
minimal_time c priority pred_timestamp >>=? fun minimal_time ->
minimal_time c priority pred_timestamp
>>=? fun minimal_time ->
let timestamp = Alpha_context.Timestamp.current c in
Lwt.return
(record_trace (Timestamp_too_early (minimal_time, timestamp))
(record_trace
(Timestamp_too_early (minimal_time, timestamp))
Timestamp.(timestamp -? minimal_time))
let check_baking_rights c { Block_header.priority ; _ }
pred_timestamp =
let check_baking_rights c {Block_header.priority; _} pred_timestamp =
let level = Level.current c in
Roll.baking_rights_owner c level ~priority >>=? fun delegate ->
check_timestamp c priority pred_timestamp >>=? fun block_delay ->
return (delegate, block_delay)
Roll.baking_rights_owner c level ~priority
>>=? fun delegate ->
check_timestamp c priority pred_timestamp
>>=? fun block_delay -> return (delegate, block_delay)
type error += Incorrect_priority (* `Permanent *)
type error += Incorrect_number_of_endorsements (* `Permanent *)
let () =
@ -169,8 +193,10 @@ let () =
(fun () -> Incorrect_priority)
let () =
let description = "The number of endorsements must be non-negative and \
at most the endosers_per_block constant." in
let description =
"The number of endorsements must be non-negative and at most the \
endosers_per_block constant."
in
register_error_kind
`Permanent
~id:"incorrect_number_of_endorsements"
@ -181,89 +207,109 @@ let () =
(function Incorrect_number_of_endorsements -> Some () | _ -> None)
(fun () -> Incorrect_number_of_endorsements)
let baking_reward ctxt ~block_priority:prio ~included_endorsements:num_endo =
fail_unless Compare.Int.(prio >= 0) Incorrect_priority >>=? fun () ->
let max_endorsements = Constants.endorsers_per_block ctxt in
fail_unless Compare.Int.(num_endo >= 0 && num_endo <= max_endorsements)
Incorrect_number_of_endorsements >>=? fun () ->
let prio_factor_denominator = Int64.(succ (of_int prio)) in
let endo_factor_numerator = Int64.of_int (8 + 2 * num_endo / max_endorsements) in
let endo_factor_denominator = 10L in
Lwt.return
Tez.(
Constants.block_reward ctxt *? endo_factor_numerator >>? fun val1 ->
val1 /? endo_factor_denominator >>? fun val2 ->
val2 /? prio_factor_denominator)
let rec reward_for_priority reward_per_prio prio =
match reward_per_prio with
| [] ->
(* Empty reward list in parameters means no rewards *)
Tez.zero
| [last] ->
last
| first :: rest ->
if Compare.Int.(prio <= 0) then first
else reward_for_priority rest (pred prio)
let endorsing_reward ctxt ~block_priority:prio n =
if Compare.Int.(prio >= 0)
then
Lwt.return
Tez.(Constants.endorsement_reward ctxt /? (Int64.(succ (of_int prio)))) >>=? fun tez ->
Lwt.return Tez.(tez *? Int64.of_int n)
else fail Incorrect_priority
let baking_reward ctxt ~block_priority ~included_endorsements =
fail_unless Compare.Int.(block_priority >= 0) Incorrect_priority
>>=? fun () ->
fail_unless
Compare.Int.(
included_endorsements >= 0
&& included_endorsements <= Constants.endorsers_per_block ctxt)
Incorrect_number_of_endorsements
>>=? fun () ->
let reward_per_endorsement =
reward_for_priority
(Constants.baking_reward_per_endorsement ctxt)
block_priority
in
Lwt.return Tez.(reward_per_endorsement *? Int64.of_int included_endorsements)
let endorsing_reward ctxt ~block_priority num_slots =
fail_unless Compare.Int.(block_priority >= 0) Incorrect_priority
>>=? fun () ->
let reward_per_endorsement =
reward_for_priority (Constants.endorsement_reward ctxt) block_priority
in
Lwt.return Tez.(reward_per_endorsement *? Int64.of_int num_slots)
let baking_priorities c level =
let rec f priority =
Roll.baking_rights_owner c level ~priority >>=? fun delegate ->
return (LCons (delegate, (fun () -> f (succ priority))))
Roll.baking_rights_owner c level ~priority
>>=? fun delegate -> return (LCons (delegate, fun () -> f (succ priority)))
in
f 0
let endorsement_rights c level =
let endorsement_rights ctxt level =
fold_left_s
(fun acc slot ->
Roll.endorsement_rights_owner c level ~slot >>=? fun pk ->
Roll.endorsement_rights_owner ctxt level ~slot
>>=? fun pk ->
let pkh = Signature.Public_key.hash pk in
let right =
match Signature.Public_key_hash.Map.find_opt pkh acc with
| None -> (pk, [slot], false)
| Some (pk, slots, used) -> (pk, slot :: slots, used) in
| None ->
(pk, [slot], false)
| Some (pk, slots, used) ->
(pk, slot :: slots, used)
in
return (Signature.Public_key_hash.Map.add pkh right acc))
Signature.Public_key_hash.Map.empty
(0 --> (Constants.endorsers_per_block c - 1))
(0 --> (Constants.endorsers_per_block ctxt - 1))
let check_endorsement_rights ctxt chain_id (op : Kind.endorsement Operation.t) =
let check_endorsement_rights ctxt chain_id (op : Kind.endorsement Operation.t)
=
let current_level = Level.current ctxt in
let Single (Endorsement { level ; _ }) = op.protocol_data.contents in
begin
if Raw_level.(succ level = current_level.level) then
let (Single (Endorsement {level; _})) = op.protocol_data.contents in
( if Raw_level.(succ level = current_level.level) then
return (Alpha_context.allowed_endorsements ctxt)
else
endorsement_rights ctxt (Level.from_raw ctxt level)
end >>=? fun endorsements ->
else endorsement_rights ctxt (Level.from_raw ctxt level) )
>>=? fun endorsements ->
match
Signature.Public_key_hash.Map.fold (* no find_first *)
(fun pkh (pk, slots, used) acc ->
match Operation.check_signature_sync pk chain_id op with
| Error _ -> acc
| Ok () -> Some (pkh, slots, used))
endorsements None
| Error _ ->
acc
| Ok () ->
Some (pkh, slots, used))
endorsements
None
with
| None -> fail Unexpected_endorsement
| Some v -> return v
| None ->
fail Unexpected_endorsement
| Some v ->
return v
let select_delegate delegate delegate_list max_priority =
let rec loop acc l n =
if Compare.Int.(n >= max_priority)
then return (List.rev acc)
if Compare.Int.(n >= max_priority) then return (List.rev acc)
else
let LCons (pk, t) = l in
let (LCons (pk, t)) = l in
let acc =
if Signature.Public_key_hash.equal delegate (Signature.Public_key.hash pk)
if
Signature.Public_key_hash.equal
delegate
(Signature.Public_key.hash pk)
then n :: acc
else acc in
t () >>=? fun t ->
loop acc t (succ n)
else acc
in
t () >>=? fun t -> loop acc t (succ n)
in
loop [] delegate_list 0
let first_baking_priorities
ctxt
?(max_priority = 32)
delegate level =
baking_priorities ctxt level >>=? fun delegate_list ->
select_delegate delegate delegate_list max_priority
let first_baking_priorities ctxt ?(max_priority = 32) delegate level =
baking_priorities ctxt level
>>=? fun delegate_list -> select_delegate delegate delegate_list max_priority
let check_hash hash stamp_threshold =
let bytes = Block_hash.to_bytes hash in
@ -273,18 +319,19 @@ let check_hash hash stamp_threshold =
let check_header_proof_of_work_stamp shell contents stamp_threshold =
let hash =
Block_header.hash
{ shell ; protocol_data = { contents ; signature = Signature.zero } } in
{shell; protocol_data = {contents; signature = Signature.zero}}
in
check_hash hash stamp_threshold
let check_proof_of_work_stamp ctxt block =
let proof_of_work_threshold = Constants.proof_of_work_threshold ctxt in
if check_header_proof_of_work_stamp
if
check_header_proof_of_work_stamp
block.Block_header.shell
block.protocol_data.contents
proof_of_work_threshold then
return_unit
else
fail Invalid_stamp
proof_of_work_threshold
then return_unit
else fail Invalid_stamp
let check_signature block chain_id key =
let check_signature key
@ -292,65 +339,69 @@ let check_signature block chain_id key =
let unsigned_header =
Data_encoding.Binary.to_bytes_exn
Block_header.unsigned_encoding
(shell, contents) in
Signature.check ~watermark:(Block_header chain_id) key signature unsigned_header in
if check_signature key block then
return_unit
(shell, contents)
in
Signature.check
~watermark:(Block_header chain_id)
key
signature
unsigned_header
in
if check_signature key block then return_unit
else
fail (Invalid_block_signature (Block_header.hash block,
Signature.Public_key.hash key))
fail
(Invalid_block_signature
(Block_header.hash block, Signature.Public_key.hash key))
let max_fitness_gap _ctxt = 1L
let check_fitness_gap ctxt (block : Block_header.t) =
let current_fitness = Fitness.current ctxt in
Lwt.return (Fitness.to_int64 block.shell.fitness) >>=? fun announced_fitness ->
Lwt.return (Fitness.to_int64 block.shell.fitness)
>>=? fun announced_fitness ->
let gap = Int64.sub announced_fitness current_fitness in
if Compare.Int64.(gap <= 0L || max_fitness_gap ctxt < gap) then
fail (Invalid_fitness_gap (max_fitness_gap ctxt, gap))
else
return_unit
else return_unit
let last_of_a_cycle ctxt l =
Compare.Int32.(Int32.succ l.Level.cycle_position =
Constants.blocks_per_cycle ctxt)
Compare.Int32.(
Int32.succ l.Level.cycle_position = Constants.blocks_per_cycle ctxt)
let dawn_of_a_new_cycle ctxt =
let level = Level.current ctxt in
if last_of_a_cycle ctxt level then
return_some level.cycle
else
return_none
if last_of_a_cycle ctxt level then return_some level.cycle else return_none
let minimum_allowed_endorsements ctxt ~block_delay =
let minimum = Constants.initial_endorsers ctxt in
let delay_per_missing_endorsement =
Int64.to_int
(Period.to_seconds
(Constants.delay_per_missing_endorsement ctxt))
(Period.to_seconds (Constants.delay_per_missing_endorsement ctxt))
in
let reduced_time_constraint =
let delay = Int64.to_int (Period.to_seconds block_delay) in
if Compare.Int.(delay_per_missing_endorsement = 0) then
delay
else
delay / delay_per_missing_endorsement
if Compare.Int.(delay_per_missing_endorsement = 0) then delay
else delay / delay_per_missing_endorsement
in
Compare.Int.max 0 (minimum - reduced_time_constraint)
let minimal_valid_time ctxt ~priority ~endorsing_power =
let predecessor_timestamp = Timestamp.current ctxt in
minimal_time ctxt
priority predecessor_timestamp >>=? fun minimal_time ->
minimal_time ctxt priority predecessor_timestamp
>>=? fun minimal_time ->
let minimal_required_endorsements = Constants.initial_endorsers ctxt in
let delay_per_missing_endorsement =
Constants.delay_per_missing_endorsement ctxt
in
let missing_endorsements =
Compare.Int.max 0 (minimal_required_endorsements - endorsing_power) in
match Period.mult
Compare.Int.max 0 (minimal_required_endorsements - endorsing_power)
in
match
Period.mult
(Int32.of_int missing_endorsements)
delay_per_missing_endorsement with
delay_per_missing_endorsement
with
| Ok delay ->
return (Time.add minimal_time (Period.to_seconds delay))
| Error _ as err -> Lwt.return err
| Error _ as err ->
Lwt.return err

View File

@ -23,15 +23,24 @@
(* *)
(*****************************************************************************)
open Alpha_context
open Misc
type error += Invalid_fitness_gap of int64 * int64 (* `Permanent *)
type error += Timestamp_too_early of Timestamp.t * Timestamp.t (* `Permanent *)
type error += Invalid_block_signature of Block_hash.t * Signature.Public_key_hash.t (* `Permanent *)
type error += Timestamp_too_early of Timestamp.t * Timestamp.t
(* `Permanent *)
type error +=
| Invalid_block_signature of Block_hash.t * Signature.Public_key_hash.t
(* `Permanent *)
type error += Unexpected_endorsement
type error += Invalid_signature (* `Permanent *)
type error += Invalid_stamp (* `Permanent *)
(** [minimal_time ctxt priority pred_block_time] returns the minimal
@ -46,7 +55,9 @@ val minimal_time: context -> int -> Time.t -> Time.t tzresult Lwt.t
* the timestamp is coherent with the announced slot.
*)
val check_baking_rights :
context -> Block_header.contents -> Time.t ->
context ->
Block_header.contents ->
Time.t ->
(public_key * Period.t) tzresult Lwt.t
(** For a given level computes who has the right to
@ -60,23 +71,26 @@ val endorsement_rights:
(** Check that the operation was signed by a delegate allowed
to endorse at the level specified by the endorsement. *)
val check_endorsement_rights :
context -> Chain_id.t -> Kind.endorsement Operation.t ->
context ->
Chain_id.t ->
Kind.endorsement Operation.t ->
(public_key_hash * int list * bool) tzresult Lwt.t
(** Returns the baking reward calculated w.r.t a given priority [p] and a
number [e] of included endorsements as follows:
(block_reward / (p+1)) * (0.8 + 0.2 * e / endorsers_per_block)
*)
val baking_reward: context ->
block_priority:int -> included_endorsements:int -> Tez.t tzresult Lwt.t
number [e] of included endorsements *)
val baking_reward :
context ->
block_priority:int ->
included_endorsements:int ->
Tez.t tzresult Lwt.t
(** Returns the endorsing reward calculated w.r.t a given priority. *)
val endorsing_reward: context -> block_priority:int -> int -> Tez.t tzresult Lwt.t
val endorsing_reward :
context -> block_priority:int -> int -> Tez.t tzresult Lwt.t
(** [baking_priorities ctxt level] is the lazy list of contract's
public key hashes that are allowed to bake for [level]. *)
val baking_priorities:
context -> Level.t -> public_key lazy_list
val baking_priorities : context -> Level.t -> public_key lazy_list
(** [first_baking_priorities ctxt ?max_priority contract_hash level]
is a list of priorities of max [?max_priority] elements, where the
@ -92,7 +106,8 @@ val first_baking_priorities:
(** [check_signature ctxt chain_id block id] check if the block is
signed with the given key, and belongs to the given [chain_id] *)
val check_signature: Block_header.t -> Chain_id.t -> public_key -> unit tzresult Lwt.t
val check_signature :
Block_header.t -> Chain_id.t -> public_key -> unit tzresult Lwt.t
(** Checks if the header that would be built from the given components
is valid for the given diffculty. The signature is not passed as it
@ -107,12 +122,12 @@ val check_proof_of_work_stamp:
(** check if the gap between the fitness of the current context
and the given block is within the protocol parameters *)
val check_fitness_gap:
context -> Block_header.t -> unit tzresult Lwt.t
val check_fitness_gap : context -> Block_header.t -> unit tzresult Lwt.t
val dawn_of_a_new_cycle : context -> Cycle.t option tzresult Lwt.t
val earlier_predecessor_timestamp: context -> Level.t -> Timestamp.t tzresult Lwt.t
val earlier_predecessor_timestamp :
context -> Level.t -> Timestamp.t tzresult Lwt.t
(** Since Emmy+
@ -145,7 +160,4 @@ val minimum_allowed_endorsements: context -> block_delay:Period.t -> int
`endorsing_power` argument), it returns the minimum time at which
the next block can be baked. *)
val minimal_valid_time :
context ->
priority:int ->
endorsing_power: int ->
Time.t tzresult Lwt.t
context -> priority:int -> endorsing_power:int -> Time.t tzresult Lwt.t

View File

@ -23,17 +23,22 @@
(* *)
(*****************************************************************************)
module H = Blake2B.Make(Base58)(struct
module H =
Blake2B.Make
(Base58)
(struct
let name = "Blinded public key hash"
let title = "A blinded public key hash"
let b58check_prefix = "\001\002\049\223"
let size = Some Ed25519.Public_key_hash.size
end)
include H
let () =
Base58.check_encoded_prefix b58check_encoding "btz1" 37
let () = Base58.check_encoded_prefix b58check_encoding "btz1" 37
let of_ed25519_pkh activation_code pkh =
hash_bytes ~key:activation_code [Ed25519.Public_key_hash.to_bytes pkh]
@ -41,6 +46,7 @@ let of_ed25519_pkh activation_code pkh =
type activation_code = MBytes.t
let activation_code_size = Ed25519.Public_key_hash.size
let activation_code_encoding = Data_encoding.Fixed.bytes activation_code_size
let activation_code_of_hex h =

View File

@ -26,9 +26,11 @@
include S.HASH
val encoding : t Data_encoding.t
val rpc_arg : t RPC_arg.t
type activation_code
val activation_code_encoding : activation_code Data_encoding.t
val of_ed25519_pkh : activation_code -> Ed25519.Public_key_hash.t -> t

View File

@ -25,15 +25,9 @@
(** Block header *)
type t = {
shell: Block_header.shell_header ;
protocol_data: protocol_data ;
}
type t = {shell : Block_header.shell_header; protocol_data : protocol_data}
and protocol_data = {
contents: contents ;
signature: Signature.t ;
}
and protocol_data = {contents : contents; signature : Signature.t}
and contents = {
priority : int;
@ -44,64 +38,61 @@ and contents = {
type block_header = t
type raw = Block_header.t
type shell_header = Block_header.shell_header
let raw_encoding = Block_header.encoding
let shell_header_encoding = Block_header.shell_header_encoding
let contents_encoding =
let open Data_encoding in
def "block_header.alpha.unsigned_contents" @@
conv
def "block_header.alpha.unsigned_contents"
@@ conv
(fun {priority; seed_nonce_hash; proof_of_work_nonce} ->
(priority, proof_of_work_nonce, seed_nonce_hash))
(fun (priority, proof_of_work_nonce, seed_nonce_hash) ->
{priority; seed_nonce_hash; proof_of_work_nonce})
(obj3
(req "priority" uint16)
(req "proof_of_work_nonce"
(req
"proof_of_work_nonce"
(Fixed.bytes Constants_repr.proof_of_work_nonce_size))
(opt "seed_nonce_hash" Nonce_hash.encoding))
let protocol_data_encoding =
let open Data_encoding in
def "block_header.alpha.signed_contents" @@
conv
def "block_header.alpha.signed_contents"
@@ conv
(fun {contents; signature} -> (contents, signature))
(fun (contents, signature) -> {contents; signature})
(merge_objs
contents_encoding
(obj1 (req "signature" Signature.encoding)))
let raw { shell ; protocol_data ; } =
let raw {shell; protocol_data} =
let protocol_data =
Data_encoding.Binary.to_bytes_exn
protocol_data_encoding
protocol_data in
Data_encoding.Binary.to_bytes_exn protocol_data_encoding protocol_data
in
{Block_header.shell; protocol_data}
let unsigned_encoding =
let open Data_encoding in
merge_objs
Block_header.shell_header_encoding
contents_encoding
merge_objs Block_header.shell_header_encoding contents_encoding
let encoding =
let open Data_encoding in
def "block_header.alpha.full_header" @@
conv
(fun { shell ; protocol_data } ->
(shell, protocol_data))
(fun (shell, protocol_data) ->
{ shell ; protocol_data })
(merge_objs
Block_header.shell_header_encoding
protocol_data_encoding)
def "block_header.alpha.full_header"
@@ conv
(fun {shell; protocol_data} -> (shell, protocol_data))
(fun (shell, protocol_data) -> {shell; protocol_data})
(merge_objs Block_header.shell_header_encoding protocol_data_encoding)
(** Constants *)
let max_header_length =
let fake_shell = {
let fake_shell =
{
Block_header.level = 0l;
proto_level = 0;
predecessor = Block_hash.zero;
@ -112,27 +103,28 @@ let max_header_length =
context = Context_hash.zero;
}
and fake_contents =
{ priority = 0 ;
{
priority = 0;
proof_of_work_nonce =
MBytes.create Constants_repr.proof_of_work_nonce_size;
seed_nonce_hash = Some Nonce_hash.zero
} in
seed_nonce_hash = Some Nonce_hash.zero;
}
in
Data_encoding.Binary.length
encoding
{ shell = fake_shell ;
protocol_data = {
contents = fake_contents ;
signature = Signature.zero ;
}
{
shell = fake_shell;
protocol_data = {contents = fake_contents; signature = Signature.zero};
}
(** Header parsing entry point *)
let hash_raw = Block_header.hash
let hash {shell; protocol_data} =
Block_header.hash
{ shell ;
{
shell;
protocol_data =
Data_encoding.Binary.to_bytes_exn
protocol_data_encoding
protocol_data }
Data_encoding.Binary.to_bytes_exn protocol_data_encoding protocol_data;
}

View File

@ -23,15 +23,9 @@
(* *)
(*****************************************************************************)
type t = {
shell: Block_header.shell_header ;
protocol_data: protocol_data ;
}
type t = {shell : Block_header.shell_header; protocol_data : protocol_data}
and protocol_data = {
contents: contents ;
signature: Signature.t ;
}
and protocol_data = {contents : contents; signature : Signature.t}
and contents = {
priority : int;
@ -42,19 +36,26 @@ and contents = {
type block_header = t
type raw = Block_header.t
type shell_header = Block_header.shell_header
val raw : block_header -> raw
val encoding : block_header Data_encoding.encoding
val raw_encoding : raw Data_encoding.t
val contents_encoding : contents Data_encoding.t
val unsigned_encoding : (Block_header.shell_header * contents) Data_encoding.t
val protocol_data_encoding : protocol_data Data_encoding.encoding
val shell_header_encoding : shell_header Data_encoding.encoding
val max_header_length: int
(** The maximum size of block headers in bytes *)
val max_header_length : int
val hash : block_header -> Block_hash.t
val hash_raw : raw -> Block_hash.t

View File

@ -26,100 +26,128 @@
open Misc
let init_account ctxt
({ public_key_hash ; public_key ; amount }: Parameters_repr.bootstrap_account) =
({public_key_hash; public_key; amount} : Parameters_repr.bootstrap_account)
=
let contract = Contract_repr.implicit_contract public_key_hash in
Contract_storage.credit ctxt contract amount >>=? fun ctxt ->
Contract_storage.credit ctxt contract amount
>>=? fun ctxt ->
match public_key with
| Some public_key ->
Contract_storage.reveal_manager_key ctxt public_key_hash public_key >>=? fun ctxt ->
Delegate_storage.set ctxt contract (Some public_key_hash) >>=? fun ctxt ->
Contract_storage.reveal_manager_key ctxt public_key_hash public_key
>>=? fun ctxt ->
Delegate_storage.set ctxt contract (Some public_key_hash)
>>=? fun ctxt -> return ctxt
| None ->
return ctxt
| None -> return ctxt
let init_contract ~typecheck ctxt
({delegate; amount; script} : Parameters_repr.bootstrap_contract) =
Contract_storage.fresh_contract_from_current_nonce ctxt >>=? fun (ctxt, contract) ->
typecheck ctxt script >>=? fun (script, ctxt) ->
Contract_storage.originate ctxt contract
Contract_storage.fresh_contract_from_current_nonce ctxt
>>=? fun (ctxt, contract) ->
typecheck ctxt script
>>=? fun (script, ctxt) ->
Contract_storage.originate
ctxt
contract
~balance:amount
~prepaid_bootstrap_storage:true
~script
~delegate:(Some delegate) >>=? fun ctxt ->
return ctxt
~delegate:(Some delegate)
>>=? fun ctxt -> return ctxt
let init ctxt ~typecheck ?ramp_up_cycles ?no_reward_cycles accounts contracts =
let nonce =
Operation_hash.hash_bytes
[ MBytes.of_string "Un festival de GADT." ] in
Operation_hash.hash_bytes [MBytes.of_string "Un festival de GADT."]
in
let ctxt = Raw_context.init_origination_nonce ctxt nonce in
fold_left_s init_account ctxt accounts >>=? fun ctxt ->
fold_left_s (init_contract ~typecheck) ctxt contracts >>=? fun ctxt ->
begin
match no_reward_cycles with
| None -> return ctxt
fold_left_s init_account ctxt accounts
>>=? fun ctxt ->
fold_left_s (init_contract ~typecheck) ctxt contracts
>>=? fun ctxt ->
( match no_reward_cycles with
| None ->
return ctxt
| Some cycles ->
(* Store pending ramp ups. *)
let constants = Raw_context.constants ctxt in
(* Start without reward *)
Raw_context.patch_constants ctxt
(fun c ->
{ c with
block_reward = Tez_repr.zero ;
endorsement_reward = Tez_repr.zero }) >>= fun ctxt ->
(* Start without rewards *)
Raw_context.patch_constants ctxt (fun c ->
{
c with
baking_reward_per_endorsement = [Tez_repr.zero];
endorsement_reward = [Tez_repr.zero];
})
>>= fun ctxt ->
(* Store the final reward. *)
Storage.Ramp_up.Rewards.init ctxt
Storage.Ramp_up.Rewards.init
ctxt
(Cycle_repr.of_int32_exn (Int32.of_int cycles))
(constants.block_reward,
constants.endorsement_reward)
end >>=? fun ctxt ->
(constants.baking_reward_per_endorsement, constants.endorsement_reward)
)
>>=? fun ctxt ->
match ramp_up_cycles with
| None -> return ctxt
| None ->
return ctxt
| Some cycles ->
(* Store pending ramp ups. *)
let constants = Raw_context.constants ctxt in
Lwt.return Tez_repr.(constants.block_security_deposit /? Int64.of_int cycles) >>=? fun block_step ->
Lwt.return Tez_repr.(constants.endorsement_security_deposit /? Int64.of_int cycles) >>=? fun endorsement_step ->
Lwt.return
Tez_repr.(constants.block_security_deposit /? Int64.of_int cycles)
>>=? fun block_step ->
Lwt.return
Tez_repr.(
constants.endorsement_security_deposit /? Int64.of_int cycles)
>>=? fun endorsement_step ->
(* Start without security_deposit *)
Raw_context.patch_constants ctxt
(fun c ->
{ c with
Raw_context.patch_constants ctxt (fun c ->
{
c with
block_security_deposit = Tez_repr.zero;
endorsement_security_deposit = Tez_repr.zero }) >>= fun ctxt ->
endorsement_security_deposit = Tez_repr.zero;
})
>>= fun ctxt ->
fold_left_s
(fun ctxt cycle ->
Lwt.return Tez_repr.(block_step *? Int64.of_int cycle) >>=? fun block_security_deposit ->
Lwt.return Tez_repr.(endorsement_step *? Int64.of_int cycle) >>=? fun endorsement_security_deposit ->
Lwt.return Tez_repr.(block_step *? Int64.of_int cycle)
>>=? fun block_security_deposit ->
Lwt.return Tez_repr.(endorsement_step *? Int64.of_int cycle)
>>=? fun endorsement_security_deposit ->
let cycle = Cycle_repr.of_int32_exn (Int32.of_int cycle) in
Storage.Ramp_up.Security_deposits.init ctxt cycle
Storage.Ramp_up.Security_deposits.init
ctxt
cycle
(block_security_deposit, endorsement_security_deposit))
ctxt
(1 --> (cycles - 1)) >>=? fun ctxt ->
(1 --> (cycles - 1))
>>=? fun ctxt ->
(* Store the final security deposits. *)
Storage.Ramp_up.Security_deposits.init ctxt
Storage.Ramp_up.Security_deposits.init
ctxt
(Cycle_repr.of_int32_exn (Int32.of_int cycles))
( constants.block_security_deposit,
constants.endorsement_security_deposit) >>=? fun ctxt ->
return ctxt
constants.endorsement_security_deposit )
>>=? fun ctxt -> return ctxt
let cycle_end ctxt last_cycle =
let next_cycle = Cycle_repr.succ last_cycle in
begin
Storage.Ramp_up.Rewards.get_option ctxt next_cycle >>=? function
| None -> return ctxt
| Some (block_reward, endorsement_reward) ->
Storage.Ramp_up.Rewards.delete ctxt next_cycle >>=? fun ctxt ->
Raw_context.patch_constants ctxt
(fun c ->
{ c with block_reward ;
endorsement_reward }) >>= fun ctxt ->
Storage.Ramp_up.Rewards.get_option ctxt next_cycle
>>=? (function
| None ->
return ctxt
| Some (baking_reward_per_endorsement, endorsement_reward) ->
Storage.Ramp_up.Rewards.delete ctxt next_cycle
>>=? fun ctxt ->
Raw_context.patch_constants ctxt (fun c ->
{c with baking_reward_per_endorsement; endorsement_reward})
>>= fun ctxt -> return ctxt)
>>=? fun ctxt ->
Storage.Ramp_up.Security_deposits.get_option ctxt next_cycle
>>=? function
| None ->
return ctxt
end >>=? fun ctxt ->
Storage.Ramp_up.Security_deposits.get_option ctxt next_cycle >>=? function
| None -> return ctxt
| Some (block_security_deposit, endorsement_security_deposit) ->
Storage.Ramp_up.Security_deposits.delete ctxt next_cycle >>=? fun ctxt ->
Raw_context.patch_constants ctxt
(fun c ->
{ c with block_security_deposit ;
endorsement_security_deposit }) >>= fun ctxt ->
return ctxt
Storage.Ramp_up.Security_deposits.delete ctxt next_cycle
>>=? fun ctxt ->
Raw_context.patch_constants ctxt (fun c ->
{c with block_security_deposit; endorsement_security_deposit})
>>= fun ctxt -> return ctxt

View File

@ -25,16 +25,16 @@
val init :
Raw_context.t ->
typecheck:(Raw_context.t -> Script_repr.t ->
((Script_repr.t * Contract_storage.big_map_diff option) * Raw_context.t)
tzresult Lwt.t) ->
typecheck:(Raw_context.t ->
Script_repr.t ->
( (Script_repr.t * Contract_storage.big_map_diff option)
* Raw_context.t )
tzresult
Lwt.t) ->
?ramp_up_cycles:int ->
?no_reward_cycles:int ->
Parameters_repr.bootstrap_account list ->
Parameters_repr.bootstrap_contract list ->
Raw_context.t tzresult Lwt.t
val cycle_end:
Raw_context.t ->
Cycle_repr.t ->
Raw_context.t tzresult Lwt.t
val cycle_end : Raw_context.t -> Cycle_repr.t -> Raw_context.t tzresult Lwt.t

View File

@ -25,7 +25,7 @@
type t = {
blinded_public_key_hash : Blinded_public_key_hash.t;
amount : Tez_repr.t
amount : Tez_repr.t;
}
let encoding =
@ -35,6 +35,4 @@ let encoding =
(blinded_public_key_hash, amount))
(fun (blinded_public_key_hash, amount) ->
{blinded_public_key_hash; amount})
(tup2
Blinded_public_key_hash.encoding
Tez_repr.encoding)
(tup2 Blinded_public_key_hash.encoding Tez_repr.encoding)

View File

@ -24,10 +24,11 @@
(*****************************************************************************)
let get_opt = Storage.Commitments.get_option
let delete = Storage.Commitments.delete
let init ctxt commitments =
let init_commitment ctxt Commitment_repr.{blinded_public_key_hash; amount} =
Storage.Commitments.init ctxt blinded_public_key_hash amount in
fold_left_s init_commitment ctxt commitments >>=? fun ctxt ->
return ctxt
Storage.Commitments.init ctxt blinded_public_key_hash amount
in
fold_left_s init_commitment ctxt commitments >>=? fun ctxt -> return ctxt

View File

@ -24,14 +24,12 @@
(*****************************************************************************)
val init :
Raw_context.t ->
Commitment_repr.t list ->
Raw_context.t tzresult Lwt.t
Raw_context.t -> Commitment_repr.t list -> Raw_context.t tzresult Lwt.t
val get_opt :
Raw_context.t -> Blinded_public_key_hash.t ->
Raw_context.t ->
Blinded_public_key_hash.t ->
Tez_repr.t option tzresult Lwt.t
val delete :
Raw_context.t -> Blinded_public_key_hash.t ->
Raw_context.t tzresult Lwt.t
Raw_context.t -> Blinded_public_key_hash.t -> Raw_context.t tzresult Lwt.t

View File

@ -24,11 +24,17 @@
(*****************************************************************************)
let version_number_004 = "\000"
let version_number = "\001"
let proof_of_work_nonce_size = 8
let nonce_length = 32
let max_revelations_per_block = 32
let max_proposals_per_delegate = 20
let max_operation_data_length = 16 * 1024 (* 16kB *)
type fixed = {
@ -53,7 +59,8 @@ let fixed_encoding =
max_revelations_per_block,
max_operation_data_length,
max_proposals_per_delegate ) ->
{ proof_of_work_nonce_size ;
{
proof_of_work_nonce_size;
nonce_length;
max_revelations_per_block;
max_operation_data_length;
@ -66,7 +73,8 @@ let fixed_encoding =
(req "max_operation_data_length" int31)
(req "max_proposals_per_delegate" uint8))
let fixed = {
let fixed =
{
proof_of_work_nonce_size;
nonce_length;
max_revelations_per_block;
@ -74,6 +82,162 @@ let fixed = {
max_proposals_per_delegate;
}
type parametric = {
preserved_cycles : int;
blocks_per_cycle : int32;
blocks_per_commitment : int32;
blocks_per_roll_snapshot : int32;
blocks_per_voting_period : int32;
time_between_blocks : Period_repr.t list;
endorsers_per_block : int;
hard_gas_limit_per_operation : Z.t;
hard_gas_limit_per_block : Z.t;
proof_of_work_threshold : int64;
tokens_per_roll : Tez_repr.t;
michelson_maximum_type_size : int;
seed_nonce_revelation_tip : Tez_repr.t;
origination_size : int;
block_security_deposit : Tez_repr.t;
endorsement_security_deposit : Tez_repr.t;
baking_reward_per_endorsement : Tez_repr.t list;
endorsement_reward : Tez_repr.t list;
cost_per_byte : Tez_repr.t;
hard_storage_limit_per_operation : Z.t;
test_chain_duration : int64;
(* in seconds *)
quorum_min : int32;
quorum_max : int32;
min_proposal_quorum : int32;
initial_endorsers : int;
delay_per_missing_endorsement : Period_repr.t;
}
let parametric_encoding =
let open Data_encoding in
conv
(fun c ->
( ( c.preserved_cycles,
c.blocks_per_cycle,
c.blocks_per_commitment,
c.blocks_per_roll_snapshot,
c.blocks_per_voting_period,
c.time_between_blocks,
c.endorsers_per_block,
c.hard_gas_limit_per_operation,
c.hard_gas_limit_per_block ),
( ( c.proof_of_work_threshold,
c.tokens_per_roll,
c.michelson_maximum_type_size,
c.seed_nonce_revelation_tip,
c.origination_size,
c.block_security_deposit,
c.endorsement_security_deposit,
c.baking_reward_per_endorsement ),
( c.endorsement_reward,
c.cost_per_byte,
c.hard_storage_limit_per_operation,
c.test_chain_duration,
c.quorum_min,
c.quorum_max,
c.min_proposal_quorum,
c.initial_endorsers,
c.delay_per_missing_endorsement ) ) ))
(fun ( ( preserved_cycles,
blocks_per_cycle,
blocks_per_commitment,
blocks_per_roll_snapshot,
blocks_per_voting_period,
time_between_blocks,
endorsers_per_block,
hard_gas_limit_per_operation,
hard_gas_limit_per_block ),
( ( proof_of_work_threshold,
tokens_per_roll,
michelson_maximum_type_size,
seed_nonce_revelation_tip,
origination_size,
block_security_deposit,
endorsement_security_deposit,
baking_reward_per_endorsement ),
( endorsement_reward,
cost_per_byte,
hard_storage_limit_per_operation,
test_chain_duration,
quorum_min,
quorum_max,
min_proposal_quorum,
initial_endorsers,
delay_per_missing_endorsement ) ) ) ->
{
preserved_cycles;
blocks_per_cycle;
blocks_per_commitment;
blocks_per_roll_snapshot;
blocks_per_voting_period;
time_between_blocks;
endorsers_per_block;
hard_gas_limit_per_operation;
hard_gas_limit_per_block;
proof_of_work_threshold;
tokens_per_roll;
michelson_maximum_type_size;
seed_nonce_revelation_tip;
origination_size;
block_security_deposit;
endorsement_security_deposit;
baking_reward_per_endorsement;
endorsement_reward;
cost_per_byte;
hard_storage_limit_per_operation;
test_chain_duration;
quorum_min;
quorum_max;
min_proposal_quorum;
initial_endorsers;
delay_per_missing_endorsement;
})
(merge_objs
(obj9
(req "preserved_cycles" uint8)
(req "blocks_per_cycle" int32)
(req "blocks_per_commitment" int32)
(req "blocks_per_roll_snapshot" int32)
(req "blocks_per_voting_period" int32)
(req "time_between_blocks" (list Period_repr.encoding))
(req "endorsers_per_block" uint16)
(req "hard_gas_limit_per_operation" z)
(req "hard_gas_limit_per_block" z))
(merge_objs
(obj8
(req "proof_of_work_threshold" int64)
(req "tokens_per_roll" Tez_repr.encoding)
(req "michelson_maximum_type_size" uint16)
(req "seed_nonce_revelation_tip" Tez_repr.encoding)
(req "origination_size" int31)
(req "block_security_deposit" Tez_repr.encoding)
(req "endorsement_security_deposit" Tez_repr.encoding)
(req "baking_reward_per_endorsement" (list Tez_repr.encoding)))
(obj9
(req "endorsement_reward" (list Tez_repr.encoding))
(req "cost_per_byte" Tez_repr.encoding)
(req "hard_storage_limit_per_operation" z)
(req "test_chain_duration" int64)
(req "quorum_min" int32)
(req "quorum_max" int32)
(req "min_proposal_quorum" int32)
(req "initial_endorsers" uint16)
(req "delay_per_missing_endorsement" Period_repr.encoding))))
type t = {fixed : fixed; parametric : parametric}
let encoding =
let open Data_encoding in
conv
(fun {fixed; parametric} -> (fixed, parametric))
(fun (fixed, parametric) -> {fixed; parametric})
(merge_objs fixed_encoding parametric_encoding)
module Proto_005 = struct
type parametric = {
preserved_cycles : int;
blocks_per_cycle : int32;
@ -95,7 +259,8 @@ type parametric = {
endorsement_reward : Tez_repr.t;
cost_per_byte : Tez_repr.t;
hard_storage_limit_per_operation : Z.t;
test_chain_duration: int64 ; (* in seconds *)
test_chain_duration : int64;
(* in seconds *)
quorum_min : int32;
quorum_max : int32;
min_proposal_quorum : int32;
@ -132,8 +297,7 @@ let parametric_encoding =
c.quorum_max,
c.min_proposal_quorum,
c.initial_endorsers,
c.delay_per_missing_endorsement
))) )
c.delay_per_missing_endorsement ) ) ))
(fun ( ( preserved_cycles,
blocks_per_cycle,
blocks_per_commitment,
@ -160,7 +324,8 @@ let parametric_encoding =
min_proposal_quorum,
initial_endorsers,
delay_per_missing_endorsement ) ) ) ->
{ preserved_cycles ;
{
preserved_cycles;
blocks_per_cycle;
blocks_per_commitment;
blocks_per_roll_snapshot;
@ -217,17 +382,5 @@ let parametric_encoding =
(req "quorum_max" int32)
(req "min_proposal_quorum" int32)
(req "initial_endorsers" uint16)
(req "delay_per_missing_endorsement" Period_repr.encoding)
)))
type t = {
fixed : fixed ;
parametric : parametric ;
}
let encoding =
let open Data_encoding in
conv
(fun { fixed ; parametric } -> (fixed, parametric))
(fun (fixed , parametric) -> { fixed ; parametric })
(merge_objs fixed_encoding parametric_encoding)
(req "delay_per_missing_endorsement" Period_repr.encoding))))
end

View File

@ -26,10 +26,10 @@
open Alpha_context
let custom_root =
(RPC_path.(open_root / "context" / "constants") : RPC_context.t RPC_path.context)
( RPC_path.(open_root / "context" / "constants")
: RPC_context.t RPC_path.context )
module S = struct
open Data_encoding
let errors =
@ -45,21 +45,16 @@ module S = struct
~query:RPC_query.empty
~output:Alpha_context.Constants.encoding
custom_root
end
let register () =
let open Services_registration in
register0_noctxt S.errors begin fun () () ->
return (Data_encoding.Json.(schema error_encoding))
end ;
register0 S.all begin fun ctxt () () ->
register0_noctxt S.errors (fun () () ->
return Data_encoding.Json.(schema error_encoding)) ;
register0 S.all (fun ctxt () () ->
let open Constants in
return { fixed = fixed ;
parametric = parametric ctxt }
end
return {fixed; parametric = parametric ctxt})
let errors ctxt block =
RPC_context.make_call0 S.errors ctxt block () ()
let all ctxt block =
RPC_context.make_call0 S.all ctxt block () ()
let errors ctxt block = RPC_context.make_call0 S.errors ctxt block () ()
let all ctxt block = RPC_context.make_call0 S.all ctxt block () ()

View File

@ -26,10 +26,11 @@
open Alpha_context
val errors :
'a #RPC_context.simple -> 'a -> Data_encoding.json_schema shell_tzresult Lwt.t
'a #RPC_context.simple ->
'a ->
Data_encoding.json_schema shell_tzresult Lwt.t
(** Returns all the constants of the protocol *)
val all:
'a #RPC_context.simple -> 'a -> Constants.t shell_tzresult Lwt.t
val all : 'a #RPC_context.simple -> 'a -> Constants.t shell_tzresult Lwt.t
val register : unit -> unit

View File

@ -26,80 +26,105 @@
let preserved_cycles c =
let constants = Raw_context.constants c in
constants.preserved_cycles
let blocks_per_cycle c =
let constants = Raw_context.constants c in
constants.blocks_per_cycle
let blocks_per_commitment c =
let constants = Raw_context.constants c in
constants.blocks_per_commitment
let blocks_per_roll_snapshot c =
let constants = Raw_context.constants c in
constants.blocks_per_roll_snapshot
let blocks_per_voting_period c =
let constants = Raw_context.constants c in
constants.blocks_per_voting_period
let time_between_blocks c =
let constants = Raw_context.constants c in
constants.time_between_blocks
let endorsers_per_block c =
let constants = Raw_context.constants c in
constants.endorsers_per_block
let initial_endorsers c =
let constants = Raw_context.constants c in
constants.initial_endorsers
let delay_per_missing_endorsement c =
let constants = Raw_context.constants c in
constants.delay_per_missing_endorsement
let hard_gas_limit_per_operation c =
let constants = Raw_context.constants c in
constants.hard_gas_limit_per_operation
let hard_gas_limit_per_block c =
let constants = Raw_context.constants c in
constants.hard_gas_limit_per_block
let cost_per_byte c =
let constants = Raw_context.constants c in
constants.cost_per_byte
let hard_storage_limit_per_operation c =
let constants = Raw_context.constants c in
constants.hard_storage_limit_per_operation
let proof_of_work_threshold c =
let constants = Raw_context.constants c in
constants.proof_of_work_threshold
let tokens_per_roll c =
let constants = Raw_context.constants c in
constants.tokens_per_roll
let michelson_maximum_type_size c =
let constants = Raw_context.constants c in
constants.michelson_maximum_type_size
let seed_nonce_revelation_tip c =
let constants = Raw_context.constants c in
constants.seed_nonce_revelation_tip
let origination_size c =
let constants = Raw_context.constants c in
constants.origination_size
let block_security_deposit c =
let constants = Raw_context.constants c in
constants.block_security_deposit
let endorsement_security_deposit c =
let constants = Raw_context.constants c in
constants.endorsement_security_deposit
let block_reward c =
let baking_reward_per_endorsement c =
let constants = Raw_context.constants c in
constants.block_reward
constants.baking_reward_per_endorsement
let endorsement_reward c =
let constants = Raw_context.constants c in
constants.endorsement_reward
let test_chain_duration c =
let constants = Raw_context.constants c in
constants.test_chain_duration
let quorum_min c =
let constants = Raw_context.constants c in
constants.quorum_min
let quorum_max c =
let constants = Raw_context.constants c in
constants.quorum_max
let min_proposal_quorum c =
let constants = Raw_context.constants c in
constants.min_proposal_quorum
let parametric c =
Raw_context.constants c
let parametric c = Raw_context.constants c

View File

@ -26,12 +26,16 @@
(* 20 *)
let contract_hash = "\002\090\121" (* KT1(36) *)
include Blake2B.Make(Base58)(struct
include Blake2B.Make
(Base58)
(struct
let name = "Contract_hash"
let title = "A contract ID"
let b58check_prefix = contract_hash
let size = Some 20
end)
let () =
Base58.check_encoded_prefix b58check_encoding "KT1" 36
let () = Base58.check_encoded_prefix b58check_encoding "KT1" 36

View File

@ -29,14 +29,17 @@ type t =
include Compare.Make (struct
type nonrec t = t
let compare l1 l2 =
match l1, l2 with
| Implicit pkh1, Implicit pkh2 ->
match (l1, l2) with
| (Implicit pkh1, Implicit pkh2) ->
Signature.Public_key_hash.compare pkh1 pkh2
| Originated h1, Originated h2 ->
| (Originated h1, Originated h2) ->
Contract_hash.compare h1 h2
| Implicit _, Originated _ -> -1
| Originated _, Implicit _ -> 1
| (Implicit _, Originated _) ->
-1
| (Originated _, Implicit _) ->
1
end)
type contract = t
@ -44,54 +47,69 @@ type contract = t
type error += Invalid_contract_notation of string (* `Permanent *)
let to_b58check = function
| Implicit pbk -> Signature.Public_key_hash.to_b58check pbk
| Originated h -> Contract_hash.to_b58check h
| Implicit pbk ->
Signature.Public_key_hash.to_b58check pbk
| Originated h ->
Contract_hash.to_b58check h
let of_b58check s =
match Base58.decode s with
| Some (Ed25519.Public_key_hash.Data h) -> ok (Implicit (Signature.Ed25519 h))
| Some (Secp256k1.Public_key_hash.Data h) -> ok (Implicit (Signature.Secp256k1 h))
| Some (P256.Public_key_hash.Data h) -> ok (Implicit (Signature.P256 h))
| Some (Contract_hash.Data h) -> ok (Originated h)
| _ -> error (Invalid_contract_notation s)
| Some (Ed25519.Public_key_hash.Data h) ->
ok (Implicit (Signature.Ed25519 h))
| Some (Secp256k1.Public_key_hash.Data h) ->
ok (Implicit (Signature.Secp256k1 h))
| Some (P256.Public_key_hash.Data h) ->
ok (Implicit (Signature.P256 h))
| Some (Contract_hash.Data h) ->
ok (Originated h)
| _ ->
error (Invalid_contract_notation s)
let pp ppf = function
| Implicit pbk -> Signature.Public_key_hash.pp ppf pbk
| Originated h -> Contract_hash.pp ppf h
| Implicit pbk ->
Signature.Public_key_hash.pp ppf pbk
| Originated h ->
Contract_hash.pp ppf h
let pp_short ppf = function
| Implicit pbk -> Signature.Public_key_hash.pp_short ppf pbk
| Originated h -> Contract_hash.pp_short ppf h
| Implicit pbk ->
Signature.Public_key_hash.pp_short ppf pbk
| Originated h ->
Contract_hash.pp_short ppf h
let encoding =
let open Data_encoding in
def "contract_id"
~title:
"A contract handle"
def
"contract_id"
~title:"A contract handle"
~description:
"A contract notation as given to an RPC or inside scripts. \
Can be a base58 implicit contract hash \
or a base58 originated contract hash." @@
splitted
"A contract notation as given to an RPC or inside scripts. Can be a \
base58 implicit contract hash or a base58 originated contract hash."
@@ splitted
~binary:
(union ~tag_size:`Uint8 [
case (Tag 0)
(union
~tag_size:`Uint8
[ case
(Tag 0)
~title:"Implicit"
Signature.Public_key_hash.encoding
(function Implicit k -> Some k | _ -> None)
(fun k -> Implicit k);
case (Tag 1) (Fixed.add_padding Contract_hash.encoding 1)
case
(Tag 1)
(Fixed.add_padding Contract_hash.encoding 1)
~title:"Originated"
(function Originated k -> Some k | _ -> None)
(fun k -> Originated k) ;
])
(fun k -> Originated k) ])
~json:
(conv
to_b58check
(fun s ->
match of_b58check s with
| Ok s -> s
| Error _ -> Json.cannot_destruct "Invalid contract notation.")
| Ok s ->
s
| Error _ ->
Json.cannot_destruct "Invalid contract notation.")
string)
let () =
@ -109,19 +127,14 @@ let () =
let implicit_contract id = Implicit id
let originated_contract_004 id = Originated id
let is_implicit = function Implicit m -> Some m | Originated _ -> None
let is_implicit = function
| Implicit m -> Some m
| Originated _ -> None
let is_originated = function Implicit _ -> None | Originated h -> Some h
let is_originated = function
| Implicit _ -> None
| Originated h -> Some h
type origination_nonce =
{ operation_hash: Operation_hash.t ;
origination_index: int32 }
type origination_nonce = {
operation_hash : Operation_hash.t;
origination_index : int32;
}
let origination_nonce_encoding =
let open Data_encoding in
@ -129,28 +142,27 @@ let origination_nonce_encoding =
(fun {operation_hash; origination_index} ->
(operation_hash, origination_index))
(fun (operation_hash, origination_index) ->
{ operation_hash ; origination_index }) @@
obj2
(req "operation" Operation_hash.encoding)
(dft "index" int32 0l)
{operation_hash; origination_index})
@@ obj2 (req "operation" Operation_hash.encoding) (dft "index" int32 0l)
let originated_contract nonce =
let data =
Data_encoding.Binary.to_bytes_exn origination_nonce_encoding nonce in
Data_encoding.Binary.to_bytes_exn origination_nonce_encoding nonce
in
Originated (Contract_hash.hash_bytes [data])
let originated_contracts
~since:{origination_index = first; operation_hash = first_hash}
~until: ({ origination_index = last ; operation_hash = last_hash } as origination_nonce) =
~until:( {origination_index = last; operation_hash = last_hash} as
origination_nonce ) =
assert (Operation_hash.equal first_hash last_hash) ;
let rec contracts acc origination_index =
if Compare.Int32.(origination_index < first) then
acc
if Compare.Int32.(origination_index < first) then acc
else
let origination_nonce =
{ origination_nonce with origination_index } in
let origination_nonce = {origination_nonce with origination_index} in
let acc = originated_contract origination_nonce :: acc in
contracts acc (Int32.pred origination_index) in
contracts acc (Int32.pred origination_index)
in
contracts [] (Int32.pred last)
let initial_origination_nonce operation_hash =
@ -164,8 +176,11 @@ let rpc_arg =
let construct = to_b58check in
let destruct hash =
match of_b58check hash with
| Error _ -> Error "Cannot parse contract id"
| Ok contract -> Ok contract in
| Error _ ->
Error "Cannot parse contract id"
| Ok contract ->
Ok contract
in
RPC_arg.make
~descr:"A contract identifier encoded in b58check."
~name:"contract_id"
@ -174,41 +189,42 @@ let rpc_arg =
()
module Index = struct
type t = contract
let path_length = 7
let to_path c l =
let raw_key = Data_encoding.Binary.to_bytes_exn encoding c in
let `Hex key = MBytes.to_hex raw_key in
let `Hex index_key = MBytes.to_hex (Raw_hashes.blake2b raw_key) in
String.sub index_key 0 2 ::
String.sub index_key 2 2 ::
String.sub index_key 4 2 ::
String.sub index_key 6 2 ::
String.sub index_key 8 2 ::
String.sub index_key 10 2 ::
key ::
l
let (`Hex key) = MBytes.to_hex raw_key in
let (`Hex index_key) = MBytes.to_hex (Raw_hashes.blake2b raw_key) in
String.sub index_key 0 2 :: String.sub index_key 2 2
:: String.sub index_key 4 2 :: String.sub index_key 6 2
:: String.sub index_key 8 2 :: String.sub index_key 10 2 :: key :: l
let of_path = function
| [] | [_] | [_;_] | [_;_;_] | [_;_;_;_] | [_;_;_;_;_] | [_;_;_;_;_;_]
| []
| [_]
| [_; _]
| [_; _; _]
| [_; _; _; _]
| [_; _; _; _; _]
| [_; _; _; _; _; _]
| _ :: _ :: _ :: _ :: _ :: _ :: _ :: _ :: _ ->
None
| [index1; index2; index3; index4; index5; index6; key] ->
let raw_key = MBytes.of_hex (`Hex key) in
let `Hex index_key = MBytes.to_hex (Raw_hashes.blake2b raw_key) in
assert Compare.String.(String.sub index_key 0 2 = index1) ;
assert Compare.String.(String.sub index_key 2 2 = index2) ;
assert Compare.String.(String.sub index_key 4 2 = index3) ;
assert Compare.String.(String.sub index_key 6 2 = index4) ;
assert Compare.String.(String.sub index_key 8 2 = index5) ;
assert Compare.String.(String.sub index_key 10 2 = index6) ;
let (`Hex index_key) = MBytes.to_hex (Raw_hashes.blake2b raw_key) in
assert (Compare.String.(String.sub index_key 0 2 = index1)) ;
assert (Compare.String.(String.sub index_key 2 2 = index2)) ;
assert (Compare.String.(String.sub index_key 4 2 = index3)) ;
assert (Compare.String.(String.sub index_key 6 2 = index4)) ;
assert (Compare.String.(String.sub index_key 8 2 = index5)) ;
assert (Compare.String.(String.sub index_key 10 2 = index6)) ;
Data_encoding.Binary.of_bytes encoding raw_key
let rpc_arg = rpc_arg
let encoding = encoding
let compare = compare
let encoding = encoding
let compare = compare
end

View File

@ -26,6 +26,7 @@
type t = private
| Implicit of Signature.Public_key_hash.t
| Originated of Contract_hash.t
type contract = t
include Compare.S with type t := contract
@ -34,9 +35,6 @@ include Compare.S with type t := contract
val implicit_contract : Signature.Public_key_hash.t -> contract
(** Only for migration from proto_004 *)
val originated_contract_004 : Contract_hash.t -> contract
val is_implicit : contract -> Signature.Public_key_hash.t option
(** {2 Originated contracts} *)
@ -50,7 +48,8 @@ type origination_nonce
val originated_contract : origination_nonce -> contract
val originated_contracts : since: origination_nonce -> until: origination_nonce -> contract list
val originated_contracts :
since:origination_nonce -> until:origination_nonce -> contract list
val initial_origination_nonce : Operation_hash.t -> origination_nonce
@ -58,7 +57,6 @@ val incr_origination_nonce : origination_nonce -> origination_nonce
val is_originated : contract -> Contract_hash.t option
(** {2 Human readable notation} *)
type error += Invalid_contract_notation of string (* `Permanent *)

View File

@ -26,10 +26,12 @@
open Alpha_context
let custom_root =
(RPC_path.(open_root / "context" / "contracts") : RPC_context.t RPC_path.context)
( RPC_path.(open_root / "context" / "contracts")
: RPC_context.t RPC_path.context )
let big_map_root =
(RPC_path.(open_root / "context" / "big_maps") : RPC_context.t RPC_path.context)
( RPC_path.(open_root / "context" / "big_maps")
: RPC_context.t RPC_path.context )
type info = {
balance : Tez.t;
@ -44,15 +46,14 @@ let info_encoding =
(fun {balance; delegate; script; counter} ->
(balance, delegate, script, counter))
(fun (balance, delegate, script, counter) ->
{balance ; delegate ; script ; counter}) @@
obj4
{balance; delegate; script; counter})
@@ obj4
(req "balance" Tez.encoding)
(opt "delegate" Signature.Public_key_hash.encoding)
(opt "script" Script.encoding)
(opt "counter" n)
module S = struct
open Data_encoding
let balance =
@ -102,27 +103,35 @@ module S = struct
~description:"Return the type of the given entrypoint of the contract"
~query:RPC_query.empty
~output:Script.expr_encoding
RPC_path.(custom_root /: Contract.rpc_arg / "entrypoints" /: RPC_arg.string)
RPC_path.(
custom_root /: Contract.rpc_arg / "entrypoints" /: RPC_arg.string)
let list_entrypoints =
RPC_service.get_service
~description:"Return the list of entrypoints of the contract"
~query:RPC_query.empty
~output: (obj2
(dft "unreachable"
~output:
(obj2
(dft
"unreachable"
(Data_encoding.list
(obj1 (req "path" (Data_encoding.list Michelson_v1_primitives.prim_encoding))))
(obj1
(req
"path"
(Data_encoding.list
Michelson_v1_primitives.prim_encoding))))
[])
(req "entrypoints"
(assoc Script.expr_encoding)))
(req "entrypoints" (assoc Script.expr_encoding)))
RPC_path.(custom_root /: Contract.rpc_arg / "entrypoints")
let contract_big_map_get_opt =
RPC_service.post_service
~description: "Access the value associated with a key in a big map of the contract (deprecated)."
~description:
"Access the value associated with a key in a big map of the contract \
(deprecated)."
~query:RPC_query.empty
~input: (obj2
~input:
(obj2
(req "key" Script.expr_encoding)
(req "type" Script.expr_encoding))
~output:(option Script.expr_encoding)
@ -149,159 +158,217 @@ module S = struct
~query:RPC_query.empty
~output:(list Contract.encoding)
custom_root
end
let register () =
let open Services_registration in
register0 S.list begin fun ctxt () () ->
Contract.list ctxt >>= return
end ;
register0 S.list (fun ctxt () () -> Contract.list ctxt >>= return) ;
let register_field s f =
register1 s (fun ctxt contract () () ->
Contract.exists ctxt contract >>=? function
| true -> f ctxt contract
| false -> raise Not_found) in
Contract.exists ctxt contract
>>=? function true -> f ctxt contract | false -> raise Not_found)
in
let register_opt_field s f =
register_field s
(fun ctxt a1 ->
f ctxt a1 >>=? function
| None -> raise Not_found
| Some v -> return v) in
register_field s (fun ctxt a1 ->
f ctxt a1 >>=? function None -> raise Not_found | Some v -> return v)
in
let do_big_map_get ctxt id key =
let open Script_ir_translator in
let ctxt = Gas.set_unlimited ctxt in
Big_map.exists ctxt id >>=? fun (ctxt, types) ->
Big_map.exists ctxt id
>>=? fun (ctxt, types) ->
match types with
| None -> raise Not_found
| Some (_, value_type) ->
Lwt.return (parse_ty ctxt
~legacy:true ~allow_big_map:false ~allow_operation:false ~allow_contract:true
| None ->
raise Not_found
| Some (_, value_type) -> (
Lwt.return
(parse_ty
ctxt
~legacy:true
~allow_big_map:false
~allow_operation:false
~allow_contract:true
(Micheline.root value_type))
>>=? fun (Ex_ty value_type, ctxt) ->
Big_map.get_opt ctxt id key >>=? fun (_ctxt, value) ->
Big_map.get_opt ctxt id key
>>=? fun (_ctxt, value) ->
match value with
| None -> raise Not_found
| None ->
raise Not_found
| Some value ->
parse_data ctxt ~legacy:true value_type (Micheline.root value) >>=? fun (value, ctxt) ->
unparse_data ctxt Readable value_type value >>=? fun (value, _ctxt) ->
return (Micheline.strip_locations value) in
parse_data ctxt ~legacy:true value_type (Micheline.root value)
>>=? fun (value, ctxt) ->
unparse_data ctxt Readable value_type value
>>=? fun (value, _ctxt) -> return (Micheline.strip_locations value)
)
in
register_field S.balance Contract.get_balance ;
register1 S.manager_key
(fun ctxt contract () () ->
register1 S.manager_key (fun ctxt contract () () ->
match Contract.is_implicit contract with
| None -> raise Not_found
| Some mgr ->
Contract.is_manager_key_revealed ctxt mgr >>=? function
| false -> return_none
| true -> Contract.get_manager_key ctxt mgr >>=? return_some) ;
| None ->
raise Not_found
| Some mgr -> (
Contract.is_manager_key_revealed ctxt mgr
>>=? function
| false ->
return_none
| true ->
Contract.get_manager_key ctxt mgr >>=? return_some )) ;
register_opt_field S.delegate Delegate.get ;
register1 S.counter
(fun ctxt contract () () ->
register1 S.counter (fun ctxt contract () () ->
match Contract.is_implicit contract with
| None -> raise Not_found
| Some mgr -> Contract.get_counter ctxt mgr) ;
register_opt_field S.script
(fun c v -> Contract.get_script c v >>=? fun (_, v) -> return v) ;
| None ->
raise Not_found
| Some mgr ->
Contract.get_counter ctxt mgr) ;
register_opt_field S.script (fun c v ->
Contract.get_script c v >>=? fun (_, v) -> return v) ;
register_opt_field S.storage (fun ctxt contract ->
Contract.get_script ctxt contract >>=? fun (ctxt, script) ->
Contract.get_script ctxt contract
>>=? fun (ctxt, script) ->
match script with
| None -> return_none
| None ->
return_none
| Some script ->
let ctxt = Gas.set_unlimited ctxt in
let open Script_ir_translator in
parse_script ctxt ~legacy:true script >>=? fun (Ex_script script, ctxt) ->
unparse_script ctxt Readable script >>=? fun (script, ctxt) ->
Script.force_decode ctxt script.storage >>=? fun (storage, _ctxt) ->
return_some storage) ;
register2 S.entrypoint_type
(fun ctxt v entrypoint () () -> Contract.get_script_code ctxt v >>=? fun (_, expr) ->
parse_script ctxt ~legacy:true script
>>=? fun (Ex_script script, ctxt) ->
unparse_script ctxt Readable script
>>=? fun (script, ctxt) ->
Script.force_decode ctxt script.storage
>>=? fun (storage, _ctxt) -> return_some storage) ;
register2 S.entrypoint_type (fun ctxt v entrypoint () () ->
Contract.get_script_code ctxt v
>>=? fun (_, expr) ->
match expr with
| None -> raise Not_found
| Some expr ->
| None ->
raise Not_found
| Some expr -> (
let ctxt = Gas.set_unlimited ctxt in
let legacy = true in
let open Script_ir_translator in
Script.force_decode ctxt expr >>=? fun (expr, _) ->
Script.force_decode ctxt expr
>>=? fun (expr, _) ->
Lwt.return
begin
parse_toplevel ~legacy expr >>? fun (arg_type, _, _, root_name) ->
parse_ty ctxt ~legacy
~allow_big_map:true ~allow_operation:false
~allow_contract:true arg_type >>? fun (Ex_ty arg_type, _) ->
Script_ir_translator.find_entrypoint ~root_name arg_type
entrypoint
end >>= function
Ok (_f , Ex_ty ty)->
unparse_ty ctxt ty >>=? fun (ty_node, _) ->
( parse_toplevel ~legacy expr
>>? fun (arg_type, _, _, root_name) ->
parse_ty
ctxt
~legacy
~allow_big_map:true
~allow_operation:false
~allow_contract:true
arg_type
>>? fun (Ex_ty arg_type, _) ->
Script_ir_translator.find_entrypoint ~root_name arg_type entrypoint
)
>>= function
| Ok (_f, Ex_ty ty) ->
unparse_ty ctxt ty
>>=? fun (ty_node, _) ->
return (Micheline.strip_locations ty_node)
| Error _ -> raise Not_found) ;
register1 S.list_entrypoints
(fun ctxt v () () -> Contract.get_script_code ctxt v >>=? fun (_, expr) ->
| Error _ ->
raise Not_found )) ;
register1 S.list_entrypoints (fun ctxt v () () ->
Contract.get_script_code ctxt v
>>=? fun (_, expr) ->
match expr with
| None -> raise Not_found
| None ->
raise Not_found
| Some expr ->
let ctxt = Gas.set_unlimited ctxt in
let legacy = true in
let open Script_ir_translator in
Script.force_decode ctxt expr >>=? fun (expr, _) ->
Script.force_decode ctxt expr
>>=? fun (expr, _) ->
Lwt.return
begin
parse_toplevel ~legacy expr >>? fun (arg_type, _, _, root_name) ->
parse_ty ctxt ~legacy
~allow_big_map:true ~allow_operation:false
~allow_contract:true arg_type >>? fun (Ex_ty arg_type, _) ->
Script_ir_translator.list_entrypoints ~root_name arg_type ctxt
end >>=? fun (unreachable_entrypoint,map) ->
( parse_toplevel ~legacy expr
>>? fun (arg_type, _, _, root_name) ->
parse_ty
ctxt
~legacy
~allow_big_map:true
~allow_operation:false
~allow_contract:true
arg_type
>>? fun (Ex_ty arg_type, _) ->
Script_ir_translator.list_entrypoints ~root_name arg_type ctxt )
>>=? fun (unreachable_entrypoint, map) ->
return
( unreachable_entrypoint,
Entrypoints_map.fold
begin fun entry (_,ty) acc ->
(entry , Micheline.strip_locations ty) ::acc end
map [])
) ;
(fun entry (_, ty) acc ->
(entry, Micheline.strip_locations ty) :: acc)
map
[] )) ;
register1 S.contract_big_map_get_opt (fun ctxt contract () (key, key_type) ->
Contract.get_script ctxt contract >>=? fun (ctxt, script) ->
Lwt.return (Script_ir_translator.parse_packable_ty ctxt ~legacy:true (Micheline.root key_type)) >>=? fun (Ex_ty key_type, ctxt) ->
Script_ir_translator.parse_data ctxt ~legacy:true key_type (Micheline.root key) >>=? fun (key, ctxt) ->
Script_ir_translator.hash_data ctxt key_type key >>=? fun (key, ctxt) ->
Contract.get_script ctxt contract
>>=? fun (ctxt, script) ->
Lwt.return
(Script_ir_translator.parse_packable_ty
ctxt
~legacy:true
(Micheline.root key_type))
>>=? fun (Ex_ty key_type, ctxt) ->
Script_ir_translator.parse_data
ctxt
~legacy:true
key_type
(Micheline.root key)
>>=? fun (key, ctxt) ->
Script_ir_translator.hash_data ctxt key_type key
>>=? fun (key, ctxt) ->
match script with
| None -> raise Not_found
| None ->
raise Not_found
| Some script ->
let ctxt = Gas.set_unlimited ctxt in
let open Script_ir_translator in
parse_script ctxt ~legacy:true script >>=? fun (Ex_script script, ctxt) ->
Script_ir_translator.collect_big_maps ctxt script.storage_type script.storage >>=? fun (ids, _ctxt) ->
parse_script ctxt ~legacy:true script
>>=? fun (Ex_script script, ctxt) ->
Script_ir_translator.collect_big_maps
ctxt
script.storage_type
script.storage
>>=? fun (ids, _ctxt) ->
let ids = Script_ir_translator.list_of_big_map_ids ids in
let rec find = function
| [] -> return_none
| (id : Z.t) :: ids -> try do_big_map_get ctxt id key >>=? return_some with Not_found -> find ids in
| [] ->
return_none
| (id : Z.t) :: ids -> (
try do_big_map_get ctxt id key >>=? return_some
with Not_found -> find ids )
in
find ids) ;
register2 S.big_map_get (fun ctxt id key () () ->
do_big_map_get ctxt id key) ;
register2 S.big_map_get (fun ctxt id key () () -> do_big_map_get ctxt id key) ;
register_field S.info (fun ctxt contract ->
Contract.get_balance ctxt contract >>=? fun balance ->
Delegate.get ctxt contract >>=? fun delegate ->
begin match Contract.is_implicit contract with
Contract.get_balance ctxt contract
>>=? fun balance ->
Delegate.get ctxt contract
>>=? fun delegate ->
( match Contract.is_implicit contract with
| Some manager ->
Contract.get_counter ctxt manager >>=? fun counter ->
return_some counter
| None -> return None
end >>=? fun counter ->
Contract.get_script ctxt contract >>=? fun (ctxt, script) ->
begin match script with
| None -> return (None, ctxt)
Contract.get_counter ctxt manager
>>=? fun counter -> return_some counter
| None ->
return None )
>>=? fun counter ->
Contract.get_script ctxt contract
>>=? fun (ctxt, script) ->
( match script with
| None ->
return (None, ctxt)
| Some script ->
let ctxt = Gas.set_unlimited ctxt in
let open Script_ir_translator in
parse_script ctxt ~legacy:true script >>=? fun (Ex_script script, ctxt) ->
unparse_script ctxt Readable script >>=? fun (script, ctxt) ->
return (Some script, ctxt)
end >>=? fun (script, _ctxt) ->
return { balance ; delegate ; script ; counter })
parse_script ctxt ~legacy:true script
>>=? fun (Ex_script script, ctxt) ->
unparse_script ctxt Readable script
>>=? fun (script, ctxt) -> return (Some script, ctxt) )
>>=? fun (script, _ctxt) -> return {balance; delegate; script; counter})
let list ctxt block =
RPC_context.make_call0 S.list ctxt block () ()
let list ctxt block = RPC_context.make_call0 S.list ctxt block () ()
let info ctxt block contract =
RPC_context.make_call1 S.info ctxt block contract () ()
@ -310,7 +377,13 @@ let balance ctxt block contract =
RPC_context.make_call1 S.balance ctxt block contract () ()
let manager_key ctxt block mgr =
RPC_context.make_call1 S.manager_key ctxt block (Contract.implicit_contract mgr) () ()
RPC_context.make_call1
S.manager_key
ctxt
block
(Contract.implicit_contract mgr)
()
()
let delegate ctxt block contract =
RPC_context.make_call1 S.delegate ctxt block contract () ()
@ -319,7 +392,13 @@ let delegate_opt ctxt block contract =
RPC_context.make_opt_call1 S.delegate ctxt block contract () ()
let counter ctxt block mgr =
RPC_context.make_call1 S.counter ctxt block (Contract.implicit_contract mgr) () ()
RPC_context.make_call1
S.counter
ctxt
block
(Contract.implicit_contract mgr)
()
()
let script ctxt block contract =
RPC_context.make_call1 S.script ctxt block contract () ()

View File

@ -25,8 +25,7 @@
open Alpha_context
val list:
'a #RPC_context.simple -> 'a -> Contract.t list shell_tzresult Lwt.t
val list : 'a #RPC_context.simple -> 'a -> Contract.t list shell_tzresult Lwt.t
type info = {
balance : Tez.t;
@ -44,42 +43,77 @@ val balance:
'a #RPC_context.simple -> 'a -> Contract.t -> Tez.t shell_tzresult Lwt.t
val manager_key :
'a #RPC_context.simple -> 'a -> public_key_hash -> public_key option shell_tzresult Lwt.t
'a #RPC_context.simple ->
'a ->
public_key_hash ->
public_key option shell_tzresult Lwt.t
val delegate :
'a #RPC_context.simple -> 'a -> Contract.t -> public_key_hash shell_tzresult Lwt.t
'a #RPC_context.simple ->
'a ->
Contract.t ->
public_key_hash shell_tzresult Lwt.t
val delegate_opt :
'a #RPC_context.simple -> 'a -> Contract.t -> public_key_hash option shell_tzresult Lwt.t
'a #RPC_context.simple ->
'a ->
Contract.t ->
public_key_hash option shell_tzresult Lwt.t
val counter :
'a #RPC_context.simple -> 'a -> public_key_hash -> counter shell_tzresult Lwt.t
'a #RPC_context.simple ->
'a ->
public_key_hash ->
counter shell_tzresult Lwt.t
val script :
'a #RPC_context.simple -> 'a -> Contract.t -> Script.t shell_tzresult Lwt.t
val script_opt :
'a #RPC_context.simple -> 'a -> Contract.t -> Script.t option shell_tzresult Lwt.t
'a #RPC_context.simple ->
'a ->
Contract.t ->
Script.t option shell_tzresult Lwt.t
val storage :
'a #RPC_context.simple -> 'a -> Contract.t -> Script.expr shell_tzresult Lwt.t
'a #RPC_context.simple ->
'a ->
Contract.t ->
Script.expr shell_tzresult Lwt.t
val entrypoint_type :
'a #RPC_context.simple -> 'a -> Contract.t -> string -> Script.expr shell_tzresult Lwt.t
'a #RPC_context.simple ->
'a ->
Contract.t ->
string ->
Script.expr shell_tzresult Lwt.t
val list_entrypoints :
'a #RPC_context.simple -> 'a -> Contract.t ->
(Michelson_v1_primitives.prim list list *
(string * Script.expr) list) shell_tzresult Lwt.t
'a #RPC_context.simple ->
'a ->
Contract.t ->
(Michelson_v1_primitives.prim list list * (string * Script.expr) list)
shell_tzresult
Lwt.t
val storage_opt :
'a #RPC_context.simple -> 'a -> Contract.t -> Script.expr option shell_tzresult Lwt.t
'a #RPC_context.simple ->
'a ->
Contract.t ->
Script.expr option shell_tzresult Lwt.t
val big_map_get :
'a #RPC_context.simple -> 'a -> Z.t -> Script_expr_hash.t ->
'a #RPC_context.simple ->
'a ->
Z.t ->
Script_expr_hash.t ->
Script.expr shell_tzresult Lwt.t
val contract_big_map_get_opt :
'a #RPC_context.simple -> 'a -> Contract.t -> Script.expr * Script.expr -> Script.expr option shell_tzresult Lwt.t
'a #RPC_context.simple ->
'a ->
Contract.t ->
Script.expr * Script.expr ->
Script.expr option shell_tzresult Lwt.t
val register : unit -> unit

View File

@ -24,28 +24,49 @@
(*****************************************************************************)
type error +=
| Balance_too_low of Contract_repr.contract * Tez_repr.t * Tez_repr.t (* `Temporary *)
| Counter_in_the_past of Contract_repr.contract * Z.t * Z.t (* `Branch *)
| Counter_in_the_future of Contract_repr.contract * Z.t * Z.t (* `Temporary *)
| Unspendable_contract of Contract_repr.contract (* `Permanent *)
| Non_existing_contract of Contract_repr.contract (* `Temporary *)
| Empty_implicit_contract of Signature.Public_key_hash.t (* `Temporary *)
| Empty_transaction of Contract_repr.t (* `Temporary *)
| Inconsistent_hash of Signature.Public_key.t * Signature.Public_key_hash.t * Signature.Public_key_hash.t (* `Permanent *)
| Inconsistent_public_key of Signature.Public_key.t * Signature.Public_key.t (* `Permanent *)
| Failure of string (* `Permanent *)
| Balance_too_low of Contract_repr.contract * Tez_repr.t * Tez_repr.t
| (* `Temporary *)
Counter_in_the_past of Contract_repr.contract * Z.t * Z.t
| (* `Branch *)
Counter_in_the_future of Contract_repr.contract * Z.t * Z.t
| (* `Temporary *)
Unspendable_contract of Contract_repr.contract
| (* `Permanent *)
Non_existing_contract of Contract_repr.contract
| (* `Temporary *)
Empty_implicit_contract of Signature.Public_key_hash.t
| (* `Temporary *)
Empty_implicit_delegated_contract of
Signature.Public_key_hash.t
| (* `Temporary *)
Empty_transaction of Contract_repr.t (* `Temporary *)
| Inconsistent_hash of
Signature.Public_key.t
* Signature.Public_key_hash.t
* Signature.Public_key_hash.t
| (* `Permanent *)
Inconsistent_public_key of
Signature.Public_key.t * Signature.Public_key.t
| (* `Permanent *)
Failure of string (* `Permanent *)
| Previously_revealed_key of Contract_repr.t (* `Permanent *)
| Unrevealed_manager_key of Contract_repr.t (* `Permanent *)
| Unrevealed_manager_key of Contract_repr.t
(* `Permanent *)
let () =
register_error_kind
`Permanent
~id:"contract.unspendable_contract"
~title:"Unspendable contract"
~description:"An operation tried to spend tokens from an unspendable contract"
~description:
"An operation tried to spend tokens from an unspendable contract"
~pp:(fun ppf c ->
Format.fprintf ppf "The tokens of contract %a can only be spent by its script"
Contract_repr.pp c)
Format.fprintf
ppf
"The tokens of contract %a can only be spent by its script"
Contract_repr.pp
c)
Data_encoding.(obj1 (req "contract" Contract_repr.encoding))
(function Unspendable_contract c -> Some c | _ -> None)
(fun c -> Unspendable_contract c) ;
@ -53,11 +74,20 @@ let () =
`Temporary
~id:"contract.balance_too_low"
~title:"Balance too low"
~description:"An operation tried to spend more tokens than the contract has"
~description:
"An operation tried to spend more tokens than the contract has"
~pp:(fun ppf (c, b, a) ->
Format.fprintf ppf "Balance of contract %a too low (%a) to spend %a"
Contract_repr.pp c Tez_repr.pp b Tez_repr.pp a)
Data_encoding.(obj3
Format.fprintf
ppf
"Balance of contract %a too low (%a) to spend %a"
Contract_repr.pp
c
Tez_repr.pp
b
Tez_repr.pp
a)
Data_encoding.(
obj3
(req "contract" Contract_repr.encoding)
(req "balance" Tez_repr.encoding)
(req "amount" Tez_repr.encoding))
@ -69,13 +99,15 @@ let () =
~title:"Invalid counter (not yet reached) in a manager operation"
~description:"An operation assumed a contract counter in the future"
~pp:(fun ppf (contract, exp, found) ->
Format.fprintf ppf
Format.fprintf
ppf
"Counter %s not yet reached for contract %a (expected %s)"
(Z.to_string found)
Contract_repr.pp contract
Contract_repr.pp
contract
(Z.to_string exp))
Data_encoding.
(obj3
Data_encoding.(
obj3
(req "contract" Contract_repr.encoding)
(req "expected" z)
(req "found" z))
@ -87,13 +119,15 @@ let () =
~title:"Invalid counter (already used) in a manager operation"
~description:"An operation assumed a contract counter in the past"
~pp:(fun ppf (contract, exp, found) ->
Format.fprintf ppf
Format.fprintf
ppf
"Counter %s already used for contract %a (expected %s)"
(Z.to_string found)
Contract_repr.pp contract
Contract_repr.pp
contract
(Z.to_string exp))
Data_encoding.
(obj3
Data_encoding.(
obj3
(req "contract" Contract_repr.encoding)
(req "expected" z)
(req "found" z))
@ -103,11 +137,11 @@ let () =
`Temporary
~id:"contract.non_existing_contract"
~title:"Non existing contract"
~description:"A contract handle is not present in the context \
(either it never was or it has been destroyed)"
~description:
"A contract handle is not present in the context (either it never was \
or it has been destroyed)"
~pp:(fun ppf contract ->
Format.fprintf ppf "Contract %a does not exist"
Contract_repr.pp contract)
Format.fprintf ppf "Contract %a does not exist" Contract_repr.pp contract)
Data_encoding.(obj1 (req "contract" Contract_repr.encoding))
(function Non_existing_contract c -> Some c | _ -> None)
(fun c -> Non_existing_contract c) ;
@ -115,13 +149,19 @@ let () =
`Permanent
~id:"contract.manager.inconsistent_hash"
~title:"Inconsistent public key hash"
~description:"A revealed manager public key is inconsistent with the announced hash"
~description:
"A revealed manager public key is inconsistent with the announced hash"
~pp:(fun ppf (k, eh, ph) ->
Format.fprintf ppf "The hash of the manager public key %s is not %a as announced but %a"
Format.fprintf
ppf
"The hash of the manager public key %s is not %a as announced but %a"
(Signature.Public_key.to_b58check k)
Signature.Public_key_hash.pp ph
Signature.Public_key_hash.pp eh)
Data_encoding.(obj3
Signature.Public_key_hash.pp
ph
Signature.Public_key_hash.pp
eh)
Data_encoding.(
obj3
(req "public_key" Signature.Public_key.encoding)
(req "expected_hash" Signature.Public_key_hash.encoding)
(req "provided_hash" Signature.Public_key_hash.encoding))
@ -131,12 +171,17 @@ let () =
`Permanent
~id:"contract.manager.inconsistent_public_key"
~title:"Inconsistent public key"
~description:"A provided manager public key is different with the public key stored in the contract"
~description:
"A provided manager public key is different with the public key stored \
in the contract"
~pp:(fun ppf (eh, ph) ->
Format.fprintf ppf "Expected manager public key %s but %s was provided"
Format.fprintf
ppf
"Expected manager public key %s but %s was provided"
(Signature.Public_key.to_b58check ph)
(Signature.Public_key.to_b58check eh))
Data_encoding.(obj2
Data_encoding.(
obj2
(req "public_key" Signature.Public_key.encoding)
(req "expected_public_key" Signature.Public_key.encoding))
(function Inconsistent_public_key (eh, ph) -> Some (eh, ph) | _ -> None)
@ -155,11 +200,14 @@ let () =
~id:"contract.unrevealed_key"
~title:"Manager operation precedes key revelation"
~description:
"One tried to apply a manager operation \
without revealing the manager public key"
"One tried to apply a manager operation without revealing the manager \
public key"
~pp:(fun ppf s ->
Format.fprintf ppf "Unrevealed manager key for contract %a."
Contract_repr.pp s)
Format.fprintf
ppf
"Unrevealed manager key for contract %a."
Contract_repr.pp
s)
Data_encoding.(obj1 (req "contract" Contract_repr.encoding))
(function Unrevealed_manager_key s -> Some s | _ -> None)
(fun s -> Unrevealed_manager_key s) ;
@ -167,11 +215,13 @@ let () =
`Branch
~id:"contract.previously_revealed_key"
~title:"Manager operation already revealed"
~description:
"One tried to revealed twice a manager public key"
~description:"One tried to revealed twice a manager public key"
~pp:(fun ppf s ->
Format.fprintf ppf "Previously revealed manager key for contract %a."
Contract_repr.pp s)
Format.fprintf
ppf
"Previously revealed manager key for contract %a."
Contract_repr.pp
s)
Data_encoding.(obj1 (req "contract" Contract_repr.encoding))
(function Previously_revealed_key s -> Some s | _ -> None)
(fun s -> Previously_revealed_key s) ;
@ -179,23 +229,43 @@ let () =
`Branch
~id:"implicit.empty_implicit_contract"
~title:"Empty implicit contract"
~description:"No manager operations are allowed on an empty implicit contract."
~description:
"No manager operations are allowed on an empty implicit contract."
~pp:(fun ppf implicit ->
Format.fprintf ppf
Format.fprintf
ppf
"Empty implicit contract (%a)"
Signature.Public_key_hash.pp implicit)
Signature.Public_key_hash.pp
implicit)
Data_encoding.(obj1 (req "implicit" Signature.Public_key_hash.encoding))
(function Empty_implicit_contract c -> Some c | _ -> None)
(fun c -> Empty_implicit_contract c) ;
register_error_kind
`Branch
~id:"implicit.empty_implicit_delegated_contract"
~title:"Empty implicit delegated contract"
~description:"Emptying an implicit delegated account is not allowed."
~pp:(fun ppf implicit ->
Format.fprintf
ppf
"Emptying implicit delegated contract (%a)"
Signature.Public_key_hash.pp
implicit)
Data_encoding.(obj1 (req "implicit" Signature.Public_key_hash.encoding))
(function Empty_implicit_delegated_contract c -> Some c | _ -> None)
(fun c -> Empty_implicit_delegated_contract c) ;
register_error_kind
`Branch
~id:"contract.empty_transaction"
~title:"Empty transaction"
~description:"Forbidden to credit 0ꜩ to a contract without code."
~pp:(fun ppf contract ->
Format.fprintf ppf
"Transaction of 0ꜩ towards a contract without code are forbidden (%a)."
Contract_repr.pp contract)
Format.fprintf
ppf
"Transaction of 0ꜩ towards a contract without code are forbidden \
(%a)."
Contract_repr.pp
contract)
Data_encoding.(obj1 (req "contract" Contract_repr.encoding))
(function Empty_transaction c -> Some c | _ -> None)
(fun c -> Empty_transaction c)
@ -222,7 +292,9 @@ type big_map_diff = big_map_diff_item list
let big_map_diff_item_encoding =
let open Data_encoding in
union
[ case (Tag 0) ~title:"update"
[ case
(Tag 0)
~title:"update"
(obj5
(req "action" (constant "update"))
(req "big_map" z)
@ -232,31 +304,28 @@ let big_map_diff_item_encoding =
(function
| Update {big_map; diff_key_hash; diff_key; diff_value} ->
Some ((), big_map, diff_key_hash, diff_key, diff_value)
| _ -> None )
| _ ->
None)
(fun ((), big_map, diff_key_hash, diff_key, diff_value) ->
Update {big_map; diff_key_hash; diff_key; diff_value});
case (Tag 1) ~title:"remove"
(obj2
(req "action" (constant "remove"))
(req "big_map" z))
(function
| Clear big_map ->
Some ((), big_map)
| _ -> None )
(fun ((), big_map) ->
Clear big_map) ;
case (Tag 2) ~title:"copy"
case
(Tag 1)
~title:"remove"
(obj2 (req "action" (constant "remove")) (req "big_map" z))
(function Clear big_map -> Some ((), big_map) | _ -> None)
(fun ((), big_map) -> Clear big_map);
case
(Tag 2)
~title:"copy"
(obj3
(req "action" (constant "copy"))
(req "source_big_map" z)
(req "destination_big_map" z))
(function
| Copy (src, dst) ->
Some ((), src, dst)
| _ -> None )
(fun ((), src, dst) ->
Copy (src, dst)) ;
case (Tag 3) ~title:"alloc"
(function Copy (src, dst) -> Some ((), src, dst) | _ -> None)
(fun ((), src, dst) -> Copy (src, dst));
case
(Tag 3)
~title:"alloc"
(obj4
(req "action" (constant "alloc"))
(req "big_map" z)
@ -265,122 +334,164 @@ let big_map_diff_item_encoding =
(function
| Alloc {big_map; key_type; value_type} ->
Some ((), big_map, key_type, value_type)
| _ -> None )
| _ ->
None)
(fun ((), big_map, key_type, value_type) ->
Alloc {big_map; key_type; value_type}) ]
let big_map_diff_encoding =
let open Data_encoding in
def "contract.big_map_diff" @@
list big_map_diff_item_encoding
def "contract.big_map_diff" @@ list big_map_diff_item_encoding
let big_map_key_cost = 65
let big_map_cost = 33
let update_script_big_map c = function
| None -> return (c, Z.zero)
| None ->
return (c, Z.zero)
| Some diff ->
fold_left_s (fun (c, total) -> function
| Clear id ->
Storage.Big_map.Total_bytes.get c id >>=? fun size ->
Storage.Big_map.remove_rec c id >>= fun c ->
if Compare.Z.(id < Z.zero) then
return (c, total)
else
return (c, Z.sub (Z.sub total size) (Z.of_int big_map_cost))
fold_left_s
(fun (c, total) -> function Clear id ->
Storage.Big_map.Total_bytes.get c id
>>=? fun size ->
Storage.Big_map.remove_rec c id
>>= fun c ->
if Compare.Z.(id < Z.zero) then return (c, total)
else return (c, Z.sub (Z.sub total size) (Z.of_int big_map_cost))
| Copy (from, to_) ->
Storage.Big_map.copy c ~from ~to_ >>=? fun c ->
if Compare.Z.(to_ < Z.zero) then
return (c, total)
Storage.Big_map.copy c ~from ~to_
>>=? fun c ->
if Compare.Z.(to_ < Z.zero) then return (c, total)
else
Storage.Big_map.Total_bytes.get c from >>=? fun size ->
Storage.Big_map.Total_bytes.get c from
>>=? fun size ->
return (c, Z.add (Z.add total size) (Z.of_int big_map_cost))
| Alloc {big_map; key_type; value_type} ->
Storage.Big_map.Total_bytes.init c big_map Z.zero >>=? fun c ->
Storage.Big_map.Total_bytes.init c big_map Z.zero
>>=? fun c ->
(* Annotations are erased to allow sharing on
[Copy]. The types from the contract code are used,
these ones are only used to make sure they are
compatible during transmissions between contracts,
and only need to be compatible, annotations
nonwhistanding. *)
let key_type = Micheline.strip_locations (Script_repr.strip_annotations (Micheline.root key_type)) in
let value_type = Micheline.strip_locations (Script_repr.strip_annotations (Micheline.root value_type)) in
Storage.Big_map.Key_type.init c big_map key_type >>=? fun c ->
Storage.Big_map.Value_type.init c big_map value_type >>=? fun c ->
if Compare.Z.(big_map < Z.zero) then
return (c, total)
else
return (c, Z.add total (Z.of_int big_map_cost))
let key_type =
Micheline.strip_locations
(Script_repr.strip_annotations (Micheline.root key_type))
in
let value_type =
Micheline.strip_locations
(Script_repr.strip_annotations (Micheline.root value_type))
in
Storage.Big_map.Key_type.init c big_map key_type
>>=? fun c ->
Storage.Big_map.Value_type.init c big_map value_type
>>=? fun c ->
if Compare.Z.(big_map < Z.zero) then return (c, total)
else return (c, Z.add total (Z.of_int big_map_cost))
| Update {big_map; diff_key_hash; diff_value = None} ->
Storage.Big_map.Contents.remove (c, big_map) diff_key_hash
>>=? fun (c, freed, existed) ->
let freed = if existed then freed + big_map_key_cost else freed in
Storage.Big_map.Total_bytes.get c big_map >>=? fun size ->
Storage.Big_map.Total_bytes.set c big_map (Z.sub size (Z.of_int freed)) >>=? fun c ->
if Compare.Z.(big_map < Z.zero) then
return (c, total)
else
return (c, Z.sub total (Z.of_int freed))
let freed =
if existed then freed + big_map_key_cost else freed
in
Storage.Big_map.Total_bytes.get c big_map
>>=? fun size ->
Storage.Big_map.Total_bytes.set
c
big_map
(Z.sub size (Z.of_int freed))
>>=? fun c ->
if Compare.Z.(big_map < Z.zero) then return (c, total)
else return (c, Z.sub total (Z.of_int freed))
| Update {big_map; diff_key_hash; diff_value = Some v} ->
Storage.Big_map.Contents.init_set (c, big_map) diff_key_hash v
>>=? fun (c, size_diff, existed) ->
let size_diff = if existed then size_diff else size_diff + big_map_key_cost in
Storage.Big_map.Total_bytes.get c big_map >>=? fun size ->
Storage.Big_map.Total_bytes.set c big_map (Z.add size (Z.of_int size_diff)) >>=? fun c ->
if Compare.Z.(big_map < Z.zero) then
return (c, total)
else
return (c, Z.add total (Z.of_int size_diff)))
(c, Z.zero) diff
let size_diff =
if existed then size_diff else size_diff + big_map_key_cost
in
Storage.Big_map.Total_bytes.get c big_map
>>=? fun size ->
Storage.Big_map.Total_bytes.set
c
big_map
(Z.add size (Z.of_int size_diff))
>>=? fun c ->
if Compare.Z.(big_map < Z.zero) then return (c, total)
else return (c, Z.add total (Z.of_int size_diff)))
(c, Z.zero)
diff
let create_base c
?(prepaid_bootstrap_storage=false) (* Free space for bootstrap contracts *)
contract
~balance ~manager ~delegate ?script () =
begin match Contract_repr.is_implicit contract with
| None -> return c
let create_base c ?(prepaid_bootstrap_storage = false)
(* Free space for bootstrap contracts *)
contract ~balance ~manager ~delegate ?script () =
( match Contract_repr.is_implicit contract with
| None ->
return c
| Some _ ->
Storage.Contract.Global_counter.get c >>=? fun counter ->
Storage.Contract.Counter.init c contract counter
end >>=? fun c ->
Storage.Contract.Balance.init c contract balance >>=? fun c ->
begin match manager with
Storage.Contract.Global_counter.get c
>>=? fun counter -> Storage.Contract.Counter.init c contract counter )
>>=? fun c ->
Storage.Contract.Balance.init c contract balance
>>=? fun c ->
( match manager with
| Some manager ->
Storage.Contract.Manager.init c contract (Manager_repr.Hash manager)
| None -> return c
end >>=? fun c ->
begin
match delegate with
| None -> return c
| None ->
return c )
>>=? fun c ->
( match delegate with
| None ->
return c
| Some delegate ->
Delegate_storage.init c contract delegate
end >>=? fun c ->
Delegate_storage.init c contract delegate )
>>=? fun c ->
match script with
| Some ({Script_repr.code; storage}, big_map_diff) ->
Storage.Contract.Code.init c contract code >>=? fun (c, code_size) ->
Storage.Contract.Storage.init c contract storage >>=? fun (c, storage_size) ->
update_script_big_map c big_map_diff >>=? fun (c, big_map_size) ->
let total_size = Z.add (Z.add (Z.of_int code_size) (Z.of_int storage_size)) big_map_size in
assert Compare.Z.(total_size >= Z.zero) ;
let prepaid_bootstrap_storage =
if prepaid_bootstrap_storage then
total_size
else
Z.zero
Storage.Contract.Code.init c contract code
>>=? fun (c, code_size) ->
Storage.Contract.Storage.init c contract storage
>>=? fun (c, storage_size) ->
update_script_big_map c big_map_diff
>>=? fun (c, big_map_size) ->
let total_size =
Z.add (Z.add (Z.of_int code_size) (Z.of_int storage_size)) big_map_size
in
Storage.Contract.Paid_storage_space.init c contract prepaid_bootstrap_storage >>=? fun c ->
assert (Compare.Z.(total_size >= Z.zero)) ;
let prepaid_bootstrap_storage =
if prepaid_bootstrap_storage then total_size else Z.zero
in
Storage.Contract.Paid_storage_space.init
c
contract
prepaid_bootstrap_storage
>>=? fun c ->
Storage.Contract.Used_storage_space.init c contract total_size
| None ->
return c
let originate c ?prepaid_bootstrap_storage contract
~balance ~script ~delegate =
create_base c ?prepaid_bootstrap_storage contract ~balance
~manager:None ~delegate ~script ()
let originate c ?prepaid_bootstrap_storage contract ~balance ~script ~delegate
=
create_base
c
?prepaid_bootstrap_storage
contract
~balance
~manager:None
~delegate
~script
()
let create_implicit c manager ~balance =
create_base c (Contract_repr.implicit_contract manager)
~balance ~manager:(Some manager) ?script:None ~delegate:None ()
create_base
c
(Contract_repr.implicit_contract manager)
~balance
~manager:(Some manager)
?script:None
~delegate:None
()
let delete c contract =
match Contract_repr.is_implicit contract with
@ -388,215 +499,255 @@ let delete c contract =
(* For non implicit contract Big_map should be cleared *)
failwith "Non implicit contracts cannot be removed"
| Some _ ->
Delegate_storage.remove c contract >>=? fun c ->
Storage.Contract.Balance.delete c contract >>=? fun c ->
Storage.Contract.Manager.delete c contract >>=? fun c ->
Storage.Contract.Counter.delete c contract >>=? fun c ->
Storage.Contract.Code.remove c contract >>=? fun (c, _, _) ->
Storage.Contract.Storage.remove c contract >>=? fun (c, _, _) ->
Storage.Contract.Paid_storage_space.remove c contract >>= fun c ->
Storage.Contract.Used_storage_space.remove c contract >>= fun c ->
return c
Delegate_storage.remove c contract
>>=? fun c ->
Storage.Contract.Balance.delete c contract
>>=? fun c ->
Storage.Contract.Manager.delete c contract
>>=? fun c ->
Storage.Contract.Counter.delete c contract
>>=? fun c ->
Storage.Contract.Code.remove c contract
>>=? fun (c, _, _) ->
Storage.Contract.Storage.remove c contract
>>=? fun (c, _, _) ->
Storage.Contract.Paid_storage_space.remove c contract
>>= fun c ->
Storage.Contract.Used_storage_space.remove c contract
>>= fun c -> return c
let allocated c contract =
Storage.Contract.Balance.get_option c contract >>=? function
| None -> return_false
| Some _ -> return_true
Storage.Contract.Balance.get_option c contract
>>=? function None -> return_false | Some _ -> return_true
let exists c contract =
match Contract_repr.is_implicit contract with
| Some _ -> return_true
| None -> allocated c contract
| Some _ ->
return_true
| None ->
allocated c contract
let must_exist c contract =
exists c contract >>=? function
| true -> return_unit
| false -> fail (Non_existing_contract contract)
exists c contract
>>=? function
| true -> return_unit | false -> fail (Non_existing_contract contract)
let must_be_allocated c contract =
allocated c contract >>=? function
| true -> return_unit
| false ->
allocated c contract
>>=? function
| true ->
return_unit
| false -> (
match Contract_repr.is_implicit contract with
| Some pkh -> fail (Empty_implicit_contract pkh)
| None -> fail (Non_existing_contract contract)
| Some pkh ->
fail (Empty_implicit_contract pkh)
| None ->
fail (Non_existing_contract contract) )
let list c = Storage.Contract.list c
let fresh_contract_from_current_nonce c =
Lwt.return (Raw_context.increment_origination_nonce c) >>=? fun (c, nonce) ->
return (c, Contract_repr.originated_contract nonce)
Lwt.return (Raw_context.increment_origination_nonce c)
>>=? fun (c, nonce) -> return (c, Contract_repr.originated_contract nonce)
let originated_from_current_nonce ~since:ctxt_since ~until:ctxt_until =
Lwt.return (Raw_context.origination_nonce ctxt_since) >>=? fun since ->
Lwt.return (Raw_context.origination_nonce ctxt_until) >>=? fun until ->
Lwt.return (Raw_context.origination_nonce ctxt_since)
>>=? fun since ->
Lwt.return (Raw_context.origination_nonce ctxt_until)
>>=? fun until ->
filter_map_s
(fun contract -> exists ctxt_until contract >>=? function
| true -> return_some contract
| false -> return_none)
(fun contract ->
exists ctxt_until contract
>>=? function true -> return_some contract | false -> return_none)
(Contract_repr.originated_contracts ~since ~until)
let check_counter_increment c manager counter =
let contract = Contract_repr.implicit_contract manager in
Storage.Contract.Counter.get c contract >>=? fun contract_counter ->
Storage.Contract.Counter.get c contract
>>=? fun contract_counter ->
let expected = Z.succ contract_counter in
if Compare.Z.(expected = counter)
then return_unit
if Compare.Z.(expected = counter) then return_unit
else if Compare.Z.(expected > counter) then
fail (Counter_in_the_past (contract, expected, counter))
else
fail (Counter_in_the_future (contract, expected, counter))
else fail (Counter_in_the_future (contract, expected, counter))
let increment_counter c manager =
let contract = Contract_repr.implicit_contract manager in
Storage.Contract.Global_counter.get c >>=? fun global_counter ->
Storage.Contract.Global_counter.set c (Z.succ global_counter) >>=? fun c ->
Storage.Contract.Counter.get c contract >>=? fun contract_counter ->
Storage.Contract.Global_counter.get c
>>=? fun global_counter ->
Storage.Contract.Global_counter.set c (Z.succ global_counter)
>>=? fun c ->
Storage.Contract.Counter.get c contract
>>=? fun contract_counter ->
Storage.Contract.Counter.set c contract (Z.succ contract_counter)
let get_script_code c contract =
Storage.Contract.Code.get_option c contract
let get_script_code c contract = Storage.Contract.Code.get_option c contract
let get_script c contract =
Storage.Contract.Code.get_option c contract >>=? fun (c, code) ->
Storage.Contract.Storage.get_option c contract >>=? fun (c, storage) ->
match code, storage with
| None, None -> return (c, None)
| Some code, Some storage -> return (c, Some { Script_repr.code ; storage })
| None, Some _ | Some _, None -> failwith "get_script"
Storage.Contract.Code.get_option c contract
>>=? fun (c, code) ->
Storage.Contract.Storage.get_option c contract
>>=? fun (c, storage) ->
match (code, storage) with
| (None, None) ->
return (c, None)
| (Some code, Some storage) ->
return (c, Some {Script_repr.code; storage})
| (None, Some _) | (Some _, None) ->
failwith "get_script"
let get_storage ctxt contract =
Storage.Contract.Storage.get_option ctxt contract >>=? function
| (ctxt, None) -> return (ctxt, None)
Storage.Contract.Storage.get_option ctxt contract
>>=? function
| (ctxt, None) ->
return (ctxt, None)
| (ctxt, Some storage) ->
Lwt.return (Script_repr.force_decode storage) >>=? fun (storage, cost) ->
Lwt.return (Raw_context.consume_gas ctxt cost) >>=? fun ctxt ->
return (ctxt, Some storage)
Lwt.return (Script_repr.force_decode storage)
>>=? fun (storage, cost) ->
Lwt.return (Raw_context.consume_gas ctxt cost)
>>=? fun ctxt -> return (ctxt, Some storage)
let get_counter c manager =
let contract = Contract_repr.implicit_contract manager in
Storage.Contract.Counter.get_option c contract >>=? function
| None -> begin
Storage.Contract.Counter.get_option c contract
>>=? function
| None -> (
match Contract_repr.is_implicit contract with
| Some _ -> Storage.Contract.Global_counter.get c
| None -> failwith "get_counter"
end
| Some v -> return v
let get_manager_004 c contract =
Storage.Contract.Manager.get_option c contract >>=? function
| None -> begin
match Contract_repr.is_implicit contract with
| Some manager -> return manager
| None -> failwith "get_manager"
end
| Some (Manager_repr.Hash v) -> return v
| Some (Manager_repr.Public_key v) -> return (Signature.Public_key.hash v)
| Some _ ->
Storage.Contract.Global_counter.get c
| None ->
failwith "get_counter" )
| Some v ->
return v
let get_manager_key c manager =
let contract = Contract_repr.implicit_contract manager in
Storage.Contract.Manager.get_option c contract >>=? function
| None -> failwith "get_manager_key"
| Some (Manager_repr.Hash _) -> fail (Unrevealed_manager_key contract)
| Some (Manager_repr.Public_key v) -> return v
Storage.Contract.Manager.get_option c contract
>>=? function
| None ->
failwith "get_manager_key"
| Some (Manager_repr.Hash _) ->
fail (Unrevealed_manager_key contract)
| Some (Manager_repr.Public_key v) ->
return v
let is_manager_key_revealed c manager =
let contract = Contract_repr.implicit_contract manager in
Storage.Contract.Manager.get_option c contract >>=? function
| None -> return_false
| Some (Manager_repr.Hash _) -> return_false
| Some (Manager_repr.Public_key _) -> return_true
Storage.Contract.Manager.get_option c contract
>>=? function
| None ->
return_false
| Some (Manager_repr.Hash _) ->
return_false
| Some (Manager_repr.Public_key _) ->
return_true
let reveal_manager_key c manager public_key =
let contract = Contract_repr.implicit_contract manager in
Storage.Contract.Manager.get c contract >>=? function
| Public_key _ -> fail (Previously_revealed_key contract)
Storage.Contract.Manager.get c contract
>>=? function
| Public_key _ ->
fail (Previously_revealed_key contract)
| Hash v ->
let actual_hash = Signature.Public_key.hash public_key in
if (Signature.Public_key_hash.equal actual_hash v) then
let v = (Manager_repr.Public_key public_key) in
Storage.Contract.Manager.set c contract v >>=? fun c ->
return c
if Signature.Public_key_hash.equal actual_hash v then
let v = Manager_repr.Public_key public_key in
Storage.Contract.Manager.set c contract v >>=? fun c -> return c
else fail (Inconsistent_hash (public_key, v, actual_hash))
let get_balance c contract =
Storage.Contract.Balance.get_option c contract >>=? function
| None -> begin
Storage.Contract.Balance.get_option c contract
>>=? function
| None -> (
match Contract_repr.is_implicit contract with
| Some _ -> return Tez_repr.zero
| None -> failwith "get_balance"
end
| Some v -> return v
| Some _ ->
return Tez_repr.zero
| None ->
failwith "get_balance" )
| Some v ->
return v
let update_script_storage c contract storage big_map_diff =
let storage = Script_repr.lazy_expr storage in
update_script_big_map c big_map_diff >>=? fun (c, big_map_size_diff) ->
Storage.Contract.Storage.set c contract storage >>=? fun (c, size_diff) ->
Storage.Contract.Used_storage_space.get c contract >>=? fun previous_size ->
let new_size = Z.add previous_size (Z.add big_map_size_diff (Z.of_int size_diff)) in
update_script_big_map c big_map_diff
>>=? fun (c, big_map_size_diff) ->
Storage.Contract.Storage.set c contract storage
>>=? fun (c, size_diff) ->
Storage.Contract.Used_storage_space.get c contract
>>=? fun previous_size ->
let new_size =
Z.add previous_size (Z.add big_map_size_diff (Z.of_int size_diff))
in
Storage.Contract.Used_storage_space.set c contract new_size
let spend c contract amount =
Storage.Contract.Balance.get c contract >>=? fun balance ->
Storage.Contract.Balance.get c contract
>>=? fun balance ->
match Tez_repr.(balance -? amount) with
| Error _ ->
fail (Balance_too_low (contract, balance, amount))
| Ok new_balance ->
Storage.Contract.Balance.set c contract new_balance >>=? fun c ->
Roll_storage.Contract.remove_amount c contract amount >>=? fun c ->
if Tez_repr.(new_balance > Tez_repr.zero) then
return c
else match Contract_repr.is_implicit contract with
| None -> return c (* Never delete originated contracts *)
| Some pkh ->
Delegate_storage.get c contract >>=? function
| Ok new_balance -> (
Storage.Contract.Balance.set c contract new_balance
>>=? fun c ->
Roll_storage.Contract.remove_amount c contract amount
>>=? fun c ->
if Tez_repr.(new_balance > Tez_repr.zero) then return c
else
match Contract_repr.is_implicit contract with
| None ->
return c (* Never delete originated contracts *)
| Some pkh -> (
Delegate_storage.get c contract
>>=? function
| Some pkh' ->
(* Don't delete "delegate" contract *)
assert (Signature.Public_key_hash.equal pkh pkh') ;
return c
if Signature.Public_key_hash.equal pkh pkh' then return c
else
(* Delegated implicit accounts cannot be emptied *)
fail (Empty_implicit_delegated_contract pkh)
| None ->
(* Delete empty implicit contract *)
delete c contract
delete c contract ) )
let credit c contract amount =
begin
if Tez_repr.(amount <> Tez_repr.zero) then
return c
( if Tez_repr.(amount <> Tez_repr.zero) then return c
else
Storage.Contract.Code.mem c contract >>=? fun (c, target_has_code) ->
fail_unless target_has_code (Empty_transaction contract) >>=? fun () ->
return c
end >>=? fun c ->
Storage.Contract.Balance.get_option c contract >>=? function
| None -> begin
Storage.Contract.Code.mem c contract
>>=? fun (c, target_has_code) ->
fail_unless target_has_code (Empty_transaction contract)
>>=? fun () -> return c )
>>=? fun c ->
Storage.Contract.Balance.get_option c contract
>>=? function
| None -> (
match Contract_repr.is_implicit contract with
| None -> fail (Non_existing_contract contract)
| None ->
fail (Non_existing_contract contract)
| Some manager ->
create_implicit c manager ~balance:amount
end
create_implicit c manager ~balance:amount )
| Some balance ->
Lwt.return Tez_repr.(amount +? balance) >>=? fun balance ->
Storage.Contract.Balance.set c contract balance >>=? fun c ->
Roll_storage.Contract.add_amount c contract amount
Lwt.return Tez_repr.(amount +? balance)
>>=? fun balance ->
Storage.Contract.Balance.set c contract balance
>>=? fun c -> Roll_storage.Contract.add_amount c contract amount
let init c =
Storage.Contract.Global_counter.init c Z.zero
>>=? fun c -> Storage.Big_map.Next.init c
let used_storage_space c contract =
Storage.Contract.Used_storage_space.get_option c contract >>=? function
| None -> return Z.zero
| Some fees -> return fees
Storage.Contract.Used_storage_space.get_option c contract
>>=? function None -> return Z.zero | Some fees -> return fees
let paid_storage_space c contract =
Storage.Contract.Paid_storage_space.get_option c contract >>=? function
| None -> return Z.zero
| Some paid_space -> return paid_space
Storage.Contract.Paid_storage_space.get_option c contract
>>=? function None -> return Z.zero | Some paid_space -> return paid_space
let set_paid_storage_space_and_return_fees_to_pay c contract new_storage_space =
Storage.Contract.Paid_storage_space.get c contract >>=? fun already_paid_space ->
if Compare.Z.(already_paid_space >= new_storage_space) then
return (Z.zero, c)
let set_paid_storage_space_and_return_fees_to_pay c contract new_storage_space
=
Storage.Contract.Paid_storage_space.get c contract
>>=? fun already_paid_space ->
if Compare.Z.(already_paid_space >= new_storage_space) then return (Z.zero, c)
else
let to_pay = Z.sub new_storage_space already_paid_space in
Storage.Contract.Paid_storage_space.set c contract new_storage_space >>=? fun c ->
return (to_pay, c)
Storage.Contract.Paid_storage_space.set c contract new_storage_space
>>=? fun c -> return (to_pay, c)

View File

@ -24,25 +24,43 @@
(*****************************************************************************)
type error +=
| Balance_too_low of Contract_repr.contract * Tez_repr.t * Tez_repr.t (* `Temporary *)
| Counter_in_the_past of Contract_repr.contract * Z.t * Z.t (* `Branch *)
| Counter_in_the_future of Contract_repr.contract * Z.t * Z.t (* `Temporary *)
| Unspendable_contract of Contract_repr.contract (* `Permanent *)
| Non_existing_contract of Contract_repr.contract (* `Temporary *)
| Empty_implicit_contract of Signature.Public_key_hash.t (* `Temporary *)
| Empty_transaction of Contract_repr.t (* `Temporary *)
| Inconsistent_hash of Signature.Public_key.t * Signature.Public_key_hash.t * Signature.Public_key_hash.t (* `Permanent *)
| Inconsistent_public_key of Signature.Public_key.t * Signature.Public_key.t (* `Permanent *)
| Failure of string (* `Permanent *)
| Balance_too_low of Contract_repr.contract * Tez_repr.t * Tez_repr.t
| (* `Temporary *)
Counter_in_the_past of Contract_repr.contract * Z.t * Z.t
| (* `Branch *)
Counter_in_the_future of Contract_repr.contract * Z.t * Z.t
| (* `Temporary *)
Unspendable_contract of Contract_repr.contract
| (* `Permanent *)
Non_existing_contract of Contract_repr.contract
| (* `Temporary *)
Empty_implicit_contract of Signature.Public_key_hash.t
| (* `Temporary *)
Empty_implicit_delegated_contract of
Signature.Public_key_hash.t
| (* `Temporary *)
Empty_transaction of Contract_repr.t (* `Temporary *)
| Inconsistent_hash of
Signature.Public_key.t
* Signature.Public_key_hash.t
* Signature.Public_key_hash.t
| (* `Permanent *)
Inconsistent_public_key of
Signature.Public_key.t * Signature.Public_key.t
| (* `Permanent *)
Failure of string (* `Permanent *)
| Previously_revealed_key of Contract_repr.t (* `Permanent *)
| Unrevealed_manager_key of Contract_repr.t (* `Permanent *)
| Unrevealed_manager_key of Contract_repr.t
(* `Permanent *)
val exists : Raw_context.t -> Contract_repr.t -> bool tzresult Lwt.t
val must_exist : Raw_context.t -> Contract_repr.t -> unit tzresult Lwt.t
val allocated : Raw_context.t -> Contract_repr.t -> bool tzresult Lwt.t
val must_be_allocated: Raw_context.t -> Contract_repr.t -> unit tzresult Lwt.t
val must_be_allocated : Raw_context.t -> Contract_repr.t -> unit tzresult Lwt.t
val list : Raw_context.t -> Contract_repr.t list Lwt.t
@ -52,28 +70,39 @@ val check_counter_increment:
val increment_counter :
Raw_context.t -> Signature.Public_key_hash.t -> Raw_context.t tzresult Lwt.t
val get_manager_004:
Raw_context.t -> Contract_repr.t -> Signature.Public_key_hash.t tzresult Lwt.t
val get_manager_key :
Raw_context.t -> Signature.Public_key_hash.t -> Signature.Public_key.t tzresult Lwt.t
Raw_context.t ->
Signature.Public_key_hash.t ->
Signature.Public_key.t tzresult Lwt.t
val is_manager_key_revealed :
Raw_context.t -> Signature.Public_key_hash.t -> bool tzresult Lwt.t
val reveal_manager_key :
Raw_context.t -> Signature.Public_key_hash.t -> Signature.Public_key.t ->
Raw_context.t ->
Signature.Public_key_hash.t ->
Signature.Public_key.t ->
Raw_context.t tzresult Lwt.t
val get_balance : Raw_context.t -> Contract_repr.t -> Tez_repr.t tzresult Lwt.t
val get_counter: Raw_context.t -> Signature.Public_key_hash.t -> Z.t tzresult Lwt.t
val get_counter :
Raw_context.t -> Signature.Public_key_hash.t -> Z.t tzresult Lwt.t
val get_script_code :
Raw_context.t -> Contract_repr.t -> (Raw_context.t * Script_repr.lazy_expr option) tzresult Lwt.t
val get_script:
Raw_context.t -> Contract_repr.t -> (Raw_context.t * Script_repr.t option) tzresult Lwt.t
val get_storage:
Raw_context.t -> Contract_repr.t -> (Raw_context.t * Script_repr.expr option) tzresult Lwt.t
Raw_context.t ->
Contract_repr.t ->
(Raw_context.t * Script_repr.lazy_expr option) tzresult Lwt.t
val get_script :
Raw_context.t ->
Contract_repr.t ->
(Raw_context.t * Script_repr.t option) tzresult Lwt.t
val get_storage :
Raw_context.t ->
Contract_repr.t ->
(Raw_context.t * Script_repr.expr option) tzresult Lwt.t
type big_map_diff_item =
| Update of {
@ -95,16 +124,22 @@ type big_map_diff = big_map_diff_item list
val big_map_diff_encoding : big_map_diff Data_encoding.t
val update_script_storage :
Raw_context.t -> Contract_repr.t ->
Script_repr.expr -> big_map_diff option ->
Raw_context.t ->
Contract_repr.t ->
Script_repr.expr ->
big_map_diff option ->
Raw_context.t tzresult Lwt.t
val credit :
Raw_context.t -> Contract_repr.t -> Tez_repr.t ->
Raw_context.t ->
Contract_repr.t ->
Tez_repr.t ->
Raw_context.t tzresult Lwt.t
val spend :
Raw_context.t -> Contract_repr.t -> Tez_repr.t ->
Raw_context.t ->
Contract_repr.t ->
Tez_repr.t ->
Raw_context.t tzresult Lwt.t
val originate :
@ -112,20 +147,26 @@ val originate:
?prepaid_bootstrap_storage:bool ->
Contract_repr.t ->
balance:Tez_repr.t ->
script:(Script_repr.t * big_map_diff option) ->
script:Script_repr.t * big_map_diff option ->
delegate:Signature.Public_key_hash.t option ->
Raw_context.t tzresult Lwt.t
val fresh_contract_from_current_nonce :
Raw_context.t -> (Raw_context.t * Contract_repr.t) tzresult Lwt.t
val originated_from_current_nonce :
since:Raw_context.t ->
until:Raw_context.t ->
Contract_repr.t list tzresult Lwt.t
val init:
Raw_context.t -> Raw_context.t tzresult Lwt.t
val init : Raw_context.t -> Raw_context.t tzresult Lwt.t
val used_storage_space : Raw_context.t -> Contract_repr.t -> Z.t tzresult Lwt.t
val paid_storage_space : Raw_context.t -> Contract_repr.t -> Z.t tzresult Lwt.t
val set_paid_storage_space_and_return_fees_to_pay: Raw_context.t -> Contract_repr.t -> Z.t -> (Z.t * Raw_context.t) tzresult Lwt.t
val set_paid_storage_space_and_return_fees_to_pay :
Raw_context.t ->
Contract_repr.t ->
Z.t ->
(Z.t * Raw_context.t) tzresult Lwt.t

View File

@ -24,15 +24,20 @@
(*****************************************************************************)
type t = int32
type cycle = t
let encoding = Data_encoding.int32
let rpc_arg =
let construct = Int32.to_string in
let destruct str =
match Int32.of_string str with
| exception _ -> Error "Cannot parse cycle"
| cycle -> Ok cycle in
| exception _ ->
Error "Cannot parse cycle"
| cycle ->
Ok cycle
in
RPC_arg.make
~descr:"A cycle integer"
~name:"block_cycle"
@ -47,39 +52,42 @@ include (Compare.Int32 : Compare.S with type t := t)
module Map = Map.Make (Compare.Int32)
let root = 0l
let succ = Int32.succ
let pred = function
| 0l -> None
| i -> Some (Int32.pred i)
let pred = function 0l -> None | i -> Some (Int32.pred i)
let add c i =
assert Compare.Int.(i > 0) ;
assert (Compare.Int.(i > 0)) ;
Int32.add c (Int32.of_int i)
let sub c i =
assert Compare.Int.(i > 0) ;
assert (Compare.Int.(i > 0)) ;
let r = Int32.sub c (Int32.of_int i) in
if Compare.Int32.(r < 0l) then None else Some r
let to_int32 i = i
let of_int32_exn l =
if Compare.Int32.(l >= 0l)
then l
if Compare.Int32.(l >= 0l) then l
else invalid_arg "Level_repr.Cycle.of_int32"
module Index = struct
type t = cycle
let path_length = 1
let to_path c l =
Int32.to_string (to_int32 c) :: l
let to_path c l = Int32.to_string (to_int32 c) :: l
let of_path = function
| [s] -> begin
try Some (Int32.of_string s)
with _ -> None
end
| _ -> None
| [s] -> (
try Some (Int32.of_string s) with _ -> None )
| _ ->
None
let rpc_arg = rpc_arg
let encoding = encoding
let compare = compare
end

View File

@ -24,19 +24,29 @@
(*****************************************************************************)
type t
type cycle = t
include Compare.S with type t := t
val encoding : cycle Data_encoding.t
val rpc_arg : cycle RPC_arg.arg
val pp : Format.formatter -> cycle -> unit
val root : cycle
val pred : cycle -> cycle option
val add : cycle -> int -> cycle
val sub : cycle -> int -> cycle option
val succ : cycle -> cycle
val to_int32 : cycle -> int32
val of_int32_exn : int32 -> cycle
module Map : S.MAP with type key = cycle

View File

@ -39,18 +39,40 @@ type info = {
let info_encoding =
let open Data_encoding in
conv
(fun { balance ; frozen_balance ; frozen_balance_by_cycle ;
staking_balance ; delegated_contracts ; delegated_balance ;
deactivated ; grace_period } ->
(balance, frozen_balance, frozen_balance_by_cycle,
staking_balance, delegated_contracts, delegated_balance,
deactivated, grace_period))
(fun (balance, frozen_balance, frozen_balance_by_cycle,
staking_balance, delegated_contracts, delegated_balance,
deactivated, grace_period) ->
{ balance ; frozen_balance ; frozen_balance_by_cycle ;
staking_balance ; delegated_contracts ; delegated_balance ;
deactivated ; grace_period })
(fun { balance;
frozen_balance;
frozen_balance_by_cycle;
staking_balance;
delegated_contracts;
delegated_balance;
deactivated;
grace_period } ->
( balance,
frozen_balance,
frozen_balance_by_cycle,
staking_balance,
delegated_contracts,
delegated_balance,
deactivated,
grace_period ))
(fun ( balance,
frozen_balance,
frozen_balance_by_cycle,
staking_balance,
delegated_contracts,
delegated_balance,
deactivated,
grace_period ) ->
{
balance;
frozen_balance;
frozen_balance_by_cycle;
staking_balance;
delegated_contracts;
delegated_balance;
deactivated;
grace_period;
})
(obj8
(req "balance" Tez.encoding)
(req "frozen_balance" Tez.encoding)
@ -62,15 +84,12 @@ let info_encoding =
(req "grace_period" Cycle.encoding))
module S = struct
let path = RPC_path.(open_root / "context" / "delegates")
open Data_encoding
type list_query = {
active: bool ;
inactive: bool ;
}
type list_query = {active : bool; inactive : bool}
let list_query : list_query RPC_query.t =
let open RPC_query in
query (fun active inactive -> {active; inactive})
@ -80,8 +99,7 @@ module S = struct
let list_delegate =
RPC_service.get_service
~description:
"Lists all registered delegates."
~description:"Lists all registered delegates."
~query:list_query
~output:(list Signature.Public_key_hash.encoding)
path
@ -90,8 +108,7 @@ module S = struct
let info =
RPC_service.get_service
~description:
"Everything about a delegate."
~description:"Everything about a delegate."
~query:RPC_query.empty
~output:info_encoding
path
@ -99,8 +116,8 @@ module S = struct
let balance =
RPC_service.get_service
~description:
"Returns the full balance of a given delegate, \
including the frozen balances."
"Returns the full balance of a given delegate, including the frozen \
balances."
~query:RPC_query.empty
~output:Tez.encoding
RPC_path.(path / "balance")
@ -108,8 +125,8 @@ module S = struct
let frozen_balance =
RPC_service.get_service
~description:
"Returns the total frozen balances of a given delegate, \
this includes the frozen deposits, rewards and fees."
"Returns the total frozen balances of a given delegate, this includes \
the frozen deposits, rewards and fees."
~query:RPC_query.empty
~output:Tez.encoding
RPC_path.(path / "frozen_balance")
@ -117,8 +134,8 @@ module S = struct
let frozen_balance_by_cycle =
RPC_service.get_service
~description:
"Returns the frozen balances of a given delegate, \
indexed by the cycle by which it will be unfrozen"
"Returns the frozen balances of a given delegate, indexed by the \
cycle by which it will be unfrozen"
~query:RPC_query.empty
~output:Delegate.frozen_balance_by_cycle_encoding
RPC_path.(path / "frozen_balance_by_cycle")
@ -127,10 +144,10 @@ module S = struct
RPC_service.get_service
~description:
"Returns the total amount of tokens delegated to a given delegate. \
This includes the balances of all the contracts that delegate \
to it, but also the balance of the delegate itself and its frozen \
fees and deposits. The rewards do not count in the delegated balance \
until they are unfrozen."
This includes the balances of all the contracts that delegate to it, \
but also the balance of the delegate itself and its frozen fees and \
deposits. The rewards do not count in the delegated balance until \
they are unfrozen."
~query:RPC_query.empty
~output:Tez.encoding
RPC_path.(path / "staking_balance")
@ -146,9 +163,9 @@ module S = struct
let delegated_balance =
RPC_service.get_service
~description:
"Returns the balances of all the contracts that delegate to a \
given delegate. This excludes the delegate's own balance and \
its frozen balances."
"Returns the balances of all the contracts that delegate to a given \
delegate. This excludes the delegate's own balance and its frozen \
balances."
~query:RPC_query.empty
~output:Tez.encoding
RPC_path.(path / "delegated_balance")
@ -165,85 +182,82 @@ module S = struct
RPC_service.get_service
~description:
"Returns the cycle by the end of which the delegate might be \
deactivated if she fails to execute any delegate action. \
A deactivated delegate might be reactivated \
(without loosing any rolls) by simply re-registering as a delegate. \
For deactivated delegates, this value contains the cycle by which \
they were deactivated."
deactivated if she fails to execute any delegate action. A \
deactivated delegate might be reactivated (without loosing any \
rolls) by simply re-registering as a delegate. For deactivated \
delegates, this value contains the cycle by which they were \
deactivated."
~query:RPC_query.empty
~output:Cycle.encoding
RPC_path.(path / "grace_period")
end
let register () =
let open Services_registration in
register0 S.list_delegate begin fun ctxt q () ->
Delegate.list ctxt >>= fun delegates ->
if q.active && q.inactive then
return delegates
register0 S.list_delegate (fun ctxt q () ->
Delegate.list ctxt
>>= fun delegates ->
if q.active && q.inactive then return delegates
else if q.active then
filter_map_s
(fun pkh ->
Delegate.deactivated ctxt pkh >>=? function
| true -> return_none
| false -> return_some pkh)
Delegate.deactivated ctxt pkh
>>=? function true -> return_none | false -> return_some pkh)
delegates
else if q.inactive then
filter_map_s
(fun pkh ->
Delegate.deactivated ctxt pkh >>=? function
| false -> return_none
| true -> return_some pkh)
delegates
else
return_nil
end ;
register1 S.info begin fun ctxt pkh () () ->
Delegate.full_balance ctxt pkh >>=? fun balance ->
Delegate.frozen_balance ctxt pkh >>=? fun frozen_balance ->
Delegate.frozen_balance_by_cycle ctxt pkh >>= fun frozen_balance_by_cycle ->
Delegate.staking_balance ctxt pkh >>=? fun staking_balance ->
Delegate.delegated_contracts ctxt pkh >>= fun delegated_contracts ->
Delegate.delegated_balance ctxt pkh >>=? fun delegated_balance ->
Delegate.deactivated ctxt pkh >>=? fun deactivated ->
Delegate.grace_period ctxt pkh >>=? fun grace_period ->
return {
balance ; frozen_balance ; frozen_balance_by_cycle ;
staking_balance ; delegated_contracts ; delegated_balance ;
deactivated ; grace_period
}
end ;
register1 S.balance begin fun ctxt pkh () () ->
Delegate.full_balance ctxt pkh
end ;
register1 S.frozen_balance begin fun ctxt pkh () () ->
Delegate.frozen_balance ctxt pkh
end ;
register1 S.frozen_balance_by_cycle begin fun ctxt pkh () () ->
Delegate.frozen_balance_by_cycle ctxt pkh >>= return
end ;
register1 S.staking_balance begin fun ctxt pkh () () ->
Delegate.staking_balance ctxt pkh
end ;
register1 S.delegated_contracts begin fun ctxt pkh () () ->
Delegate.delegated_contracts ctxt pkh >>= return
end ;
register1 S.delegated_balance begin fun ctxt pkh () () ->
Delegate.delegated_balance ctxt pkh
end ;
register1 S.deactivated begin fun ctxt pkh () () ->
Delegate.deactivated ctxt pkh
end ;
register1 S.grace_period begin fun ctxt pkh () () ->
>>=? function false -> return_none | true -> return_some pkh)
delegates
else return_nil) ;
register1 S.info (fun ctxt pkh () () ->
Delegate.full_balance ctxt pkh
>>=? fun balance ->
Delegate.frozen_balance ctxt pkh
>>=? fun frozen_balance ->
Delegate.frozen_balance_by_cycle ctxt pkh
>>= fun frozen_balance_by_cycle ->
Delegate.staking_balance ctxt pkh
>>=? fun staking_balance ->
Delegate.delegated_contracts ctxt pkh
>>= fun delegated_contracts ->
Delegate.delegated_balance ctxt pkh
>>=? fun delegated_balance ->
Delegate.deactivated ctxt pkh
>>=? fun deactivated ->
Delegate.grace_period ctxt pkh
end
>>=? fun grace_period ->
return
{
balance;
frozen_balance;
frozen_balance_by_cycle;
staking_balance;
delegated_contracts;
delegated_balance;
deactivated;
grace_period;
}) ;
register1 S.balance (fun ctxt pkh () () -> Delegate.full_balance ctxt pkh) ;
register1 S.frozen_balance (fun ctxt pkh () () ->
Delegate.frozen_balance ctxt pkh) ;
register1 S.frozen_balance_by_cycle (fun ctxt pkh () () ->
Delegate.frozen_balance_by_cycle ctxt pkh >>= return) ;
register1 S.staking_balance (fun ctxt pkh () () ->
Delegate.staking_balance ctxt pkh) ;
register1 S.delegated_contracts (fun ctxt pkh () () ->
Delegate.delegated_contracts ctxt pkh >>= return) ;
register1 S.delegated_balance (fun ctxt pkh () () ->
Delegate.delegated_balance ctxt pkh) ;
register1 S.deactivated (fun ctxt pkh () () -> Delegate.deactivated ctxt pkh) ;
register1 S.grace_period (fun ctxt pkh () () ->
Delegate.grace_period ctxt pkh)
let list ctxt block ?(active = true) ?(inactive = false) () =
RPC_context.make_call0 S.list_delegate ctxt block {active; inactive} ()
let info ctxt block pkh =
RPC_context.make_call1 S.info ctxt block pkh () ()
let info ctxt block pkh = RPC_context.make_call1 S.info ctxt block pkh () ()
let balance ctxt block pkh =
RPC_context.make_call1 S.balance ctxt block pkh () ()
@ -270,30 +284,29 @@ let grace_period ctxt block pkh =
RPC_context.make_call1 S.grace_period ctxt block pkh () ()
let requested_levels ~default ctxt cycles levels =
match levels, cycles with
| [], [] ->
match (levels, cycles) with
| ([], []) ->
return [default]
| levels, cycles ->
| (levels, cycles) ->
(* explicitly fail when requested levels or cycle are in the past...
or too far in the future... *)
let levels =
List.sort_uniq
Level.compare
(List.concat (List.map (Level.from_raw ctxt) levels ::
List.map (Level.levels_in_cycle ctxt) cycles)) in
(List.concat
( List.map (Level.from_raw ctxt) levels
:: List.map (Level.levels_in_cycle ctxt) cycles ))
in
map_s
(fun level ->
let current_level = Level.current ctxt in
if Level.(level <= current_level) then
return (level, None)
if Level.(level <= current_level) then return (level, None)
else
Baking.earlier_predecessor_timestamp
ctxt level >>=? fun timestamp ->
return (level, Some timestamp))
Baking.earlier_predecessor_timestamp ctxt level
>>=? fun timestamp -> return (level, Some timestamp))
levels
module Baking_rights = struct
type t = {
level : Raw_level.t;
delegate : Signature.Public_key_hash.t;
@ -315,11 +328,9 @@ module Baking_rights = struct
(opt "estimated_time" Timestamp.encoding))
module S = struct
open Data_encoding
let custom_root =
RPC_path.(open_root / "helpers" / "baking_rights")
let custom_root = RPC_path.(open_root / "helpers" / "baking_rights")
type baking_rights_query = {
levels : Raw_level.t list;
@ -335,7 +346,8 @@ module Baking_rights = struct
{levels; cycles; delegates; max_priority; all})
|+ multi_field "level" Raw_level.rpc_arg (fun t -> t.levels)
|+ multi_field "cycle" Cycle.rpc_arg (fun t -> t.cycles)
|+ multi_field "delegate" Signature.Public_key_hash.rpc_arg (fun t -> t.delegates)
|+ multi_field "delegate" Signature.Public_key_hash.rpc_arg (fun t ->
t.delegates)
|+ opt_field "max_priority" RPC_arg.int (fun t -> t.max_priority)
|+ flag "all" (fun t -> t.all)
|> seal
@ -344,98 +356,100 @@ module Baking_rights = struct
RPC_service.get_service
~description:
"Retrieves the list of delegates allowed to bake a block.\n\
By default, it gives the best baking priorities for bakers \
that have at least one opportunity below the 64th priority \
for the next block.\n\
Parameters `level` and `cycle` can be used to specify the \
(valid) level(s) in the past or future at which the baking \
rights have to be returned. Parameter `delegate` can be \
used to restrict the results to the given delegates. If \
parameter `all` is set, all the baking opportunities for \
each baker at each level are returned, instead of just the \
first one.\n\
By default, it gives the best baking priorities for bakers that \
have at least one opportunity below the 64th priority for the next \
block.\n\
Parameters `level` and `cycle` can be used to specify the (valid) \
level(s) in the past or future at which the baking rights have to \
be returned. Parameter `delegate` can be used to restrict the \
results to the given delegates. If parameter `all` is set, all the \
baking opportunities for each baker at each level are returned, \
instead of just the first one.\n\
Returns the list of baking slots. Also returns the minimal \
timestamps that correspond to these slots. The timestamps \
are omitted for levels in the past, and are only estimates \
for levels later that the next block, based on the \
hypothesis that all predecessor blocks were baked at the \
first priority."
timestamps that correspond to these slots. The timestamps are \
omitted for levels in the past, and are only estimates for levels \
later that the next block, based on the hypothesis that all \
predecessor blocks were baked at the first priority."
~query:baking_rights_query
~output:(list encoding)
custom_root
end
let baking_priorities ctxt max_prio (level, pred_timestamp) =
Baking.baking_priorities ctxt level >>=? fun contract_list ->
Baking.baking_priorities ctxt level
>>=? fun contract_list ->
let rec loop l acc priority =
if Compare.Int.(priority >= max_prio) then
return (List.rev acc)
if Compare.Int.(priority > max_prio) then return (List.rev acc)
else
let Misc.LCons (pk, next) = l in
let (Misc.LCons (pk, next)) = l in
let delegate = Signature.Public_key.hash pk in
begin
match pred_timestamp with
| None -> return_none
( match pred_timestamp with
| None ->
return_none
| Some pred_timestamp ->
Baking.minimal_time ctxt priority pred_timestamp >>=? fun t ->
return_some t
end>>=? fun timestamp ->
Baking.minimal_time ctxt priority pred_timestamp
>>=? fun t -> return_some t )
>>=? fun timestamp ->
let acc =
{ level = level.level ; delegate ; priority ; timestamp } :: acc in
next () >>=? fun l ->
loop l acc (priority+1) in
{level = level.level; delegate; priority; timestamp} :: acc
in
next () >>=? fun l -> loop l acc (priority + 1)
in
loop contract_list [] 0
let remove_duplicated_delegates rights =
List.rev @@ fst @@
List.fold_left
List.rev @@ fst
@@ List.fold_left
(fun (acc, previous) r ->
if Signature.Public_key_hash.Set.mem r.delegate previous then
(acc, previous)
else
(r :: acc,
Signature.Public_key_hash.Set.add r.delegate previous))
(r :: acc, Signature.Public_key_hash.Set.add r.delegate previous))
([], Signature.Public_key_hash.Set.empty)
rights
let register () =
let open Services_registration in
register0 S.baking_rights begin fun ctxt q () ->
register0 S.baking_rights (fun ctxt q () ->
requested_levels
~default:
(Level.succ ctxt (Level.current ctxt), Some (Timestamp.current ctxt))
ctxt q.cycles q.levels >>=? fun levels ->
( Level.succ ctxt (Level.current ctxt),
Some (Timestamp.current ctxt) )
ctxt
q.cycles
q.levels
>>=? fun levels ->
let max_priority =
match q.max_priority with
| None -> 64
| Some max -> max in
map_s (baking_priorities ctxt max_priority) levels >>=? fun rights ->
match q.max_priority with None -> 64 | Some max -> max
in
map_s (baking_priorities ctxt max_priority) levels
>>=? fun rights ->
let rights =
if q.all then
rights
else
List.map remove_duplicated_delegates rights in
if q.all then rights else List.map remove_duplicated_delegates rights
in
let rights = List.concat rights in
match q.delegates with
| [] -> return rights
| [] ->
return rights
| _ :: _ as delegates ->
let is_requested p =
List.exists (Signature.Public_key_hash.equal p.delegate) delegates in
return (List.filter is_requested rights)
end
List.exists
(Signature.Public_key_hash.equal p.delegate)
delegates
in
return (List.filter is_requested rights))
let get ctxt
?(levels = []) ?(cycles = []) ?(delegates = []) ?(all = false)
let get ctxt ?(levels = []) ?(cycles = []) ?(delegates = []) ?(all = false)
?max_priority block =
RPC_context.make_call0 S.baking_rights ctxt block
RPC_context.make_call0
S.baking_rights
ctxt
block
{levels; cycles; delegates; max_priority; all}
()
end
module Endorsing_rights = struct
type t = {
level : Raw_level.t;
delegate : Signature.Public_key_hash.t;
@ -457,11 +471,9 @@ module Endorsing_rights = struct
(opt "estimated_time" Timestamp.encoding))
module S = struct
open Data_encoding
let custom_root =
RPC_path.(open_root / "helpers" / "endorsing_rights")
let custom_root = RPC_path.(open_root / "helpers" / "endorsing_rights")
type endorsing_rights_query = {
levels : Raw_level.t list;
@ -471,80 +483,85 @@ module Endorsing_rights = struct
let endorsing_rights_query =
let open RPC_query in
query (fun levels cycles delegates ->
{ levels ; cycles ; delegates })
query (fun levels cycles delegates -> {levels; cycles; delegates})
|+ multi_field "level" Raw_level.rpc_arg (fun t -> t.levels)
|+ multi_field "cycle" Cycle.rpc_arg (fun t -> t.cycles)
|+ multi_field "delegate" Signature.Public_key_hash.rpc_arg (fun t -> t.delegates)
|+ multi_field "delegate" Signature.Public_key_hash.rpc_arg (fun t ->
t.delegates)
|> seal
let endorsing_rights =
RPC_service.get_service
~description:
"Retrieves the delegates allowed to endorse a block.\n\
By default, it gives the endorsement slots for delegates that \
have at least one in the next block.\n\
Parameters `level` and `cycle` can be used to specify the \
(valid) level(s) in the past or future at which the \
endorsement rights have to be returned. Parameter \
`delegate` can be used to restrict the results to the given \
delegates.\n\
Returns the list of endorsement slots. Also returns the \
minimal timestamps that correspond to these slots. The \
timestamps are omitted for levels in the past, and are only \
estimates for levels later that the next block, based on \
the hypothesis that all predecessor blocks were baked at \
the first priority."
By default, it gives the endorsement slots for delegates that have \
at least one in the next block.\n\
Parameters `level` and `cycle` can be used to specify the (valid) \
level(s) in the past or future at which the endorsement rights \
have to be returned. Parameter `delegate` can be used to restrict \
the results to the given delegates.\n\
Returns the list of endorsement slots. Also returns the minimal \
timestamps that correspond to these slots. The timestamps are \
omitted for levels in the past, and are only estimates for levels \
later that the next block, based on the hypothesis that all \
predecessor blocks were baked at the first priority."
~query:endorsing_rights_query
~output:(list encoding)
custom_root
end
let endorsement_slots ctxt (level, estimated_time) =
Baking.endorsement_rights ctxt level >>=? fun rights ->
Baking.endorsement_rights ctxt level
>>=? fun rights ->
return
(Signature.Public_key_hash.Map.fold
(fun delegate (_, slots, _) acc -> {
level = level.level ; delegate ; slots ; estimated_time
} :: acc)
rights [])
(fun delegate (_, slots, _) acc ->
{level = level.level; delegate; slots; estimated_time} :: acc)
rights
[])
let register () =
let open Services_registration in
register0 S.endorsing_rights begin fun ctxt q () ->
register0 S.endorsing_rights (fun ctxt q () ->
requested_levels
~default:(Level.current ctxt, Some (Timestamp.current ctxt))
ctxt q.cycles q.levels >>=? fun levels ->
map_s (endorsement_slots ctxt) levels >>=? fun rights ->
ctxt
q.cycles
q.levels
>>=? fun levels ->
map_s (endorsement_slots ctxt) levels
>>=? fun rights ->
let rights = List.concat rights in
match q.delegates with
| [] -> return rights
| [] ->
return rights
| _ :: _ as delegates ->
let is_requested p =
List.exists (Signature.Public_key_hash.equal p.delegate) delegates in
return (List.filter is_requested rights)
end
List.exists
(Signature.Public_key_hash.equal p.delegate)
delegates
in
return (List.filter is_requested rights))
let get ctxt
?(levels = []) ?(cycles = []) ?(delegates = []) block =
RPC_context.make_call0 S.endorsing_rights ctxt block
let get ctxt ?(levels = []) ?(cycles = []) ?(delegates = []) block =
RPC_context.make_call0
S.endorsing_rights
ctxt
block
{levels; cycles; delegates}
()
end
module Endorsing_power = struct
let endorsing_power ctxt (operation, chain_id) =
let Operation_data data = operation.protocol_data in
let (Operation_data data) = operation.protocol_data in
match data.contents with
| Single Endorsement _ ->
Baking.check_endorsement_rights ctxt chain_id {
shell = operation.shell ;
protocol_data = data ;
} >>=? fun (_, slots, _) ->
return (List.length slots)
| Single (Endorsement _) ->
Baking.check_endorsement_rights
ctxt
chain_id
{shell = operation.shell; protocol_data = data}
>>=? fun (_, slots, _) -> return (List.length slots)
| _ ->
failwith "Operation is not an endorsement"
@ -552,10 +569,12 @@ module Endorsing_power = struct
let endorsing_power =
let open Data_encoding in
RPC_service.post_service
~description:"Get the endorsing power of an endorsement, that is, \
the number of slots that the endorser has"
~description:
"Get the endorsing power of an endorsement, that is, the number of \
slots that the endorser has"
~query:RPC_query.empty
~input: (obj2
~input:
(obj2
(req "endorsement_operation" Operation.encoding)
(req "chain_id" Chain_id.encoding))
~output:int31
@ -564,37 +583,34 @@ module Endorsing_power = struct
let register () =
let open Services_registration in
register0 S.endorsing_power begin fun ctxt () (op, chain_id) ->
endorsing_power ctxt (op, chain_id)
end
register0 S.endorsing_power (fun ctxt () (op, chain_id) ->
endorsing_power ctxt (op, chain_id))
let get ctxt block op chain_id =
RPC_context.make_call0 S.endorsing_power ctxt block () (op, chain_id)
end
module Required_endorsements = struct
let required_endorsements ctxt block_delay =
return (Baking.minimum_allowed_endorsements ctxt ~block_delay)
module S = struct
type t = {block_delay : Period.t}
let required_endorsements_query =
let open RPC_query in
query (fun block_delay -> {block_delay})
|+ field "block_delay" Period.rpc_arg Period.zero (fun t -> t.block_delay)
|+ field "block_delay" Period.rpc_arg Period.zero (fun t ->
t.block_delay)
|> seal
let required_endorsements =
let open Data_encoding in
RPC_service.get_service
~description:"Minimum number of endorsements for a block to be \
valid, given a delay of the block's timestamp with \
respect to the minimum time to bake at the \
block's priority"
~description:
"Minimum number of endorsements for a block to be valid, given a \
delay of the block's timestamp with respect to the minimum time to \
bake at the block's priority"
~query:required_endorsements_query
~output:int31
RPC_path.(open_root / "required_endorsements")
@ -602,38 +618,32 @@ module Required_endorsements = struct
let register () =
let open Services_registration in
register0 S.required_endorsements begin fun ctxt ({ block_delay }) () ->
required_endorsements ctxt block_delay
end
register0 S.required_endorsements (fun ctxt {block_delay} () ->
required_endorsements ctxt block_delay)
let get ctxt block block_delay =
RPC_context.make_call0 S.required_endorsements ctxt block {block_delay} ()
end
module Minimal_valid_time = struct
let minimal_valid_time ctxt ~priority ~endorsing_power =
Baking.minimal_valid_time ctxt
~priority ~endorsing_power
Baking.minimal_valid_time ctxt ~priority ~endorsing_power
module S = struct
type t = { priority : int ;
endorsing_power : int }
type t = {priority : int; endorsing_power : int}
let minimal_valid_time_query =
let open RPC_query in
query (fun priority endorsing_power ->
{ priority ; endorsing_power })
query (fun priority endorsing_power -> {priority; endorsing_power})
|+ field "priority" RPC_arg.int 0 (fun t -> t.priority)
|+ field "endorsing_power" RPC_arg.int 0 (fun t -> t.endorsing_power)
|> seal
let minimal_valid_time =
RPC_service.get_service
~description: "Minimal valid time for a block given a priority \
and an endorsing power."
~description:
"Minimal valid time for a block given a priority and an endorsing \
power."
~query:minimal_valid_time_query
~output:Time.encoding
RPC_path.(open_root / "minimal_valid_time")
@ -641,12 +651,16 @@ module Minimal_valid_time = struct
let register () =
let open Services_registration in
register0 S.minimal_valid_time begin fun ctxt { priority ; endorsing_power } () ->
minimal_valid_time ctxt ~priority ~endorsing_power
end
register0 S.minimal_valid_time (fun ctxt {priority; endorsing_power} () ->
minimal_valid_time ctxt ~priority ~endorsing_power)
let get ctxt block priority endorsing_power =
RPC_context.make_call0 S.minimal_valid_time ctxt block { priority ; endorsing_power } ()
RPC_context.make_call0
S.minimal_valid_time
ctxt
block
{priority; endorsing_power}
()
end
let register () =
@ -658,17 +672,20 @@ let register () =
Minimal_valid_time.register ()
let endorsement_rights ctxt level =
Endorsing_rights.endorsement_slots ctxt (level, None) >>=? fun l ->
Endorsing_rights.endorsement_slots ctxt (level, None)
>>=? fun l ->
return (List.map (fun {Endorsing_rights.delegate; _} -> delegate) l)
let baking_rights ctxt max_priority =
let max = match max_priority with None -> 64 | Some m -> m in
let level = Level.current ctxt in
Baking_rights.baking_priorities ctxt max (level, None) >>=? fun l ->
return (level.level,
Baking_rights.baking_priorities ctxt max (level, None)
>>=? fun l ->
return
( level.level,
List.map
(fun { Baking_rights.delegate ; timestamp ; _ } ->
(delegate, timestamp)) l)
(fun {Baking_rights.delegate; timestamp; _} -> (delegate, timestamp))
l )
let endorsing_power ctxt operation =
Endorsing_power.endorsing_power ctxt operation

View File

@ -26,10 +26,12 @@
open Alpha_context
val list :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
?active:bool ->
?inactive:bool ->
unit -> Signature.Public_key_hash.t list shell_tzresult Lwt.t
unit ->
Signature.Public_key_hash.t list shell_tzresult Lwt.t
type info = {
balance : Tez.t;
@ -45,53 +47,60 @@ type info = {
val info_encoding : info Data_encoding.t
val info :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
Signature.Public_key_hash.t ->
info shell_tzresult Lwt.t
val balance :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
Signature.Public_key_hash.t ->
Tez.t shell_tzresult Lwt.t
val frozen_balance :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
Signature.Public_key_hash.t ->
Tez.t shell_tzresult Lwt.t
val frozen_balance_by_cycle :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
Signature.Public_key_hash.t ->
Delegate.frozen_balance Cycle.Map.t shell_tzresult Lwt.t
val staking_balance :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
Signature.Public_key_hash.t ->
Tez.t shell_tzresult Lwt.t
val delegated_contracts :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
Signature.Public_key_hash.t ->
Contract_repr.t list shell_tzresult Lwt.t
val delegated_balance :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
Signature.Public_key_hash.t ->
Tez.t shell_tzresult Lwt.t
val deactivated :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
Signature.Public_key_hash.t ->
bool shell_tzresult Lwt.t
val grace_period :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
Signature.Public_key_hash.t ->
Cycle.t shell_tzresult Lwt.t
module Baking_rights : sig
type t = {
level : Raw_level.t;
delegate : Signature.Public_key_hash.t;
@ -124,12 +133,11 @@ module Baking_rights : sig
?delegates:Signature.public_key_hash list ->
?all:bool ->
?max_priority:int ->
'a -> t list shell_tzresult Lwt.t
'a ->
t list shell_tzresult Lwt.t
end
module Endorsing_rights : sig
type t = {
level : Raw_level.t;
delegate : Signature.Public_key_hash.t;
@ -158,41 +166,32 @@ module Endorsing_rights : sig
?levels:Raw_level.t list ->
?cycles:Cycle.t list ->
?delegates:Signature.public_key_hash list ->
'a -> t list shell_tzresult Lwt.t
'a ->
t list shell_tzresult Lwt.t
end
module Endorsing_power : sig
val get :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
Alpha_context.packed_operation ->
Chain_id.t ->
int shell_tzresult Lwt.t
end
module Required_endorsements : sig
val get :
'a #RPC_context.simple -> 'a ->
Period.t -> int shell_tzresult Lwt.t
'a #RPC_context.simple -> 'a -> Period.t -> int shell_tzresult Lwt.t
end
module Minimal_valid_time : sig
val get :
'a #RPC_context.simple -> 'a ->
int -> int -> Time.t shell_tzresult Lwt.t
'a #RPC_context.simple -> 'a -> int -> int -> Time.t shell_tzresult Lwt.t
end
(* temporary export for deprecated unit test *)
val endorsement_rights :
Alpha_context.t ->
Level.t ->
public_key_hash list tzresult Lwt.t
Alpha_context.t -> Level.t -> public_key_hash list tzresult Lwt.t
val baking_rights :
Alpha_context.t ->
@ -201,18 +200,12 @@ val baking_rights:
val endorsing_power :
Alpha_context.t ->
(Alpha_context.packed_operation * Chain_id.t) ->
Alpha_context.packed_operation * Chain_id.t ->
int tzresult Lwt.t
val required_endorsements :
Alpha_context.t ->
Alpha_context.Period.t ->
int tzresult Lwt.t
Alpha_context.t -> Alpha_context.Period.t -> int tzresult Lwt.t
val minimal_valid_time:
Alpha_context.t ->
int ->
int ->
Time.t tzresult Lwt.t
val minimal_valid_time : Alpha_context.t -> int -> int -> Time.t tzresult Lwt.t
val register : unit -> unit

View File

@ -31,16 +31,18 @@ type balance =
let balance_encoding =
let open Data_encoding in
def "operation_metadata.alpha.balance" @@
union
[ case (Tag 0)
def "operation_metadata.alpha.balance"
@@ union
[ case
(Tag 0)
~title:"Contract"
(obj2
(req "kind" (constant "contract"))
(req "contract" Contract_repr.encoding))
(function Contract c -> Some ((), c) | _ -> None)
(fun ((), c) -> (Contract c)) ;
case (Tag 1)
(fun ((), c) -> Contract c);
case
(Tag 1)
~title:"Rewards"
(obj4
(req "kind" (constant "freezer"))
@ -49,7 +51,8 @@ let balance_encoding =
(req "cycle" Cycle_repr.encoding))
(function Rewards (d, l) -> Some ((), (), d, l) | _ -> None)
(fun ((), (), d, l) -> Rewards (d, l));
case (Tag 2)
case
(Tag 2)
~title:"Fees"
(obj4
(req "kind" (constant "freezer"))
@ -58,7 +61,8 @@ let balance_encoding =
(req "cycle" Cycle_repr.encoding))
(function Fees (d, l) -> Some ((), (), d, l) | _ -> None)
(fun ((), (), d, l) -> Fees (d, l));
case (Tag 3)
case
(Tag 3)
~title:"Deposits"
(obj4
(req "kind" (constant "freezer"))
@ -68,37 +72,42 @@ let balance_encoding =
(function Deposits (d, l) -> Some ((), (), d, l) | _ -> None)
(fun ((), (), d, l) -> Deposits (d, l)) ]
type balance_update =
| Debited of Tez_repr.t
| Credited of Tez_repr.t
type balance_update = Debited of Tez_repr.t | Credited of Tez_repr.t
let balance_update_encoding =
let open Data_encoding in
def "operation_metadata.alpha.balance_update" @@
obj1
(req "change"
def "operation_metadata.alpha.balance_update"
@@ obj1
(req
"change"
(conv
(function
| Credited v -> Tez_repr.to_mutez v
| Debited v -> Int64.neg (Tez_repr.to_mutez v))
(Json.wrap_error @@
fun v ->
| Credited v ->
Tez_repr.to_mutez v
| Debited v ->
Int64.neg (Tez_repr.to_mutez v))
( Json.wrap_error
@@ fun v ->
if Compare.Int64.(v < 0L) then
match Tez_repr.of_mutez (Int64.neg v) with
| Some v -> Debited v
| None -> failwith "Qty.of_mutez"
| Some v ->
Debited v
| None ->
failwith "Qty.of_mutez"
else
match Tez_repr.of_mutez v with
| Some v -> Credited v
| None -> failwith "Qty.of_mutez")
| Some v ->
Credited v
| None ->
failwith "Qty.of_mutez" )
int64))
type balance_updates = (balance * balance_update) list
let balance_updates_encoding =
let open Data_encoding in
def "operation_metadata.alpha.balance_updates" @@
list (merge_objs balance_encoding balance_update_encoding)
def "operation_metadata.alpha.balance_updates"
@@ list (merge_objs balance_encoding balance_update_encoding)
let cleanup_balance_updates balance_updates =
List.filter
@ -127,10 +136,13 @@ type error +=
| Active_delegate (* `Temporary *)
| Current_delegate (* `Temporary *)
| Empty_delegate_account of Signature.Public_key_hash.t (* `Temporary *)
| Balance_too_low_for_deposit of
{ delegate : Signature.Public_key_hash.t ;
| Balance_too_low_for_deposit of {
delegate : Signature.Public_key_hash.t;
deposit : Tez_repr.t;
balance : Tez_repr.t } (* `Temporary *)
balance : Tez_repr.t;
}
(* `Temporary *)
let () =
register_error_kind
@ -139,8 +151,11 @@ let () =
~title:"Forbidden delegate deletion"
~description:"Tried to unregister a delegate"
~pp:(fun ppf delegate ->
Format.fprintf ppf "Delegate deletion is forbidden (%a)"
Signature.Public_key_hash.pp delegate)
Format.fprintf
ppf
"Delegate deletion is forbidden (%a)"
Signature.Public_key_hash.pp
delegate)
Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding))
(function No_deletion c -> Some c | _ -> None)
(fun c -> No_deletion c) ;
@ -150,8 +165,7 @@ let () =
~title:"Delegate already active"
~description:"Useless delegate reactivation"
~pp:(fun ppf () ->
Format.fprintf ppf
"The delegate is still active, no need to refresh it")
Format.fprintf ppf "The delegate is still active, no need to refresh it")
Data_encoding.empty
(function Active_delegate -> Some () | _ -> None)
(fun () -> Active_delegate) ;
@ -161,7 +175,8 @@ let () =
~title:"Unchanged delegated"
~description:"Contract already delegated to the given delegate"
~pp:(fun ppf () ->
Format.fprintf ppf
Format.fprintf
ppf
"The contract is already delegated to the same delegate")
Data_encoding.empty
(function Current_delegate -> Some () | _ -> None)
@ -170,12 +185,15 @@ let () =
`Permanent
~id:"delegate.empty_delegate_account"
~title:"Empty delegate account"
~description:"Cannot register a delegate when its implicit account is empty"
~description:
"Cannot register a delegate when its implicit account is empty"
~pp:(fun ppf delegate ->
Format.fprintf ppf
"Delegate registration is forbidden when the delegate
implicit account is empty (%a)"
Signature.Public_key_hash.pp delegate)
Format.fprintf
ppf
"Delegate registration is forbidden when the delegate\n\
\ implicit account is empty (%a)"
Signature.Public_key_hash.pp
delegate)
Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding))
(function Empty_delegate_account c -> Some c | _ -> None)
(fun c -> Empty_delegate_account c) ;
@ -185,216 +203,249 @@ let () =
~title:"Balance too low for deposit"
~description:"Cannot freeze deposit when the balance is too low"
~pp:(fun ppf (delegate, balance, deposit) ->
Format.fprintf ppf
Format.fprintf
ppf
"Delegate %a has a too low balance (%a) to deposit %a"
Signature.Public_key_hash.pp delegate
Tez_repr.pp balance
Tez_repr.pp deposit)
Data_encoding.
(obj3
Signature.Public_key_hash.pp
delegate
Tez_repr.pp
balance
Tez_repr.pp
deposit)
Data_encoding.(
obj3
(req "delegate" Signature.Public_key_hash.encoding)
(req "balance" Tez_repr.encoding)
(req "deposit" Tez_repr.encoding))
(function Balance_too_low_for_deposit { delegate ; balance ; deposit } ->
Some (delegate, balance, deposit) | _ -> None)
(fun (delegate, balance, deposit) -> Balance_too_low_for_deposit { delegate ; balance ; deposit } )
(function
| Balance_too_low_for_deposit {delegate; balance; deposit} ->
Some (delegate, balance, deposit)
| _ ->
None)
(fun (delegate, balance, deposit) ->
Balance_too_low_for_deposit {delegate; balance; deposit})
let link c contract delegate =
Storage.Contract.Balance.get c contract >>=? fun balance ->
Roll_storage.Delegate.add_amount c delegate balance >>=? fun c ->
Storage.Contract.Delegated.add (c, Contract_repr.implicit_contract delegate) contract >>= fun c ->
return c
Storage.Contract.Balance.get c contract
>>=? fun balance ->
Roll_storage.Delegate.add_amount c delegate balance
>>=? fun c ->
Storage.Contract.Delegated.add
(c, Contract_repr.implicit_contract delegate)
contract
>>= fun c -> return c
let unlink c contract =
Storage.Contract.Balance.get c contract >>=? fun balance ->
Storage.Contract.Delegate.get_option c contract >>=? function
| None -> return c
Storage.Contract.Balance.get c contract
>>=? fun balance ->
Storage.Contract.Delegate.get_option c contract
>>=? function
| None ->
return c
| Some delegate ->
(* Removes the balance of the contract from the delegate *)
Roll_storage.Delegate.remove_amount c delegate balance >>=? fun c ->
Storage.Contract.Delegated.del (c, Contract_repr.implicit_contract delegate) contract >>= fun c ->
return c
Roll_storage.Delegate.remove_amount c delegate balance
>>=? fun c ->
Storage.Contract.Delegated.del
(c, Contract_repr.implicit_contract delegate)
contract
>>= fun c -> return c
let known c delegate =
Storage.Contract.Manager.get_option
c (Contract_repr.implicit_contract delegate) >>=? function
| None | Some (Manager_repr.Hash _) -> return_false
| Some (Manager_repr.Public_key _) -> return_true
c
(Contract_repr.implicit_contract delegate)
>>=? function
| None | Some (Manager_repr.Hash _) ->
return_false
| Some (Manager_repr.Public_key _) ->
return_true
(* A delegate is registered if its "implicit account" delegates to itself. *)
let registered c delegate =
Storage.Contract.Delegate.get_option
c (Contract_repr.implicit_contract delegate) >>=? function
c
(Contract_repr.implicit_contract delegate)
>>=? function
| Some current_delegate ->
return @@ Signature.Public_key_hash.equal delegate current_delegate
| None ->
return_false
let init ctxt contract delegate =
known ctxt delegate >>=? fun known_delegate ->
fail_unless
known_delegate
(Roll_storage.Unregistered_delegate delegate) >>=? fun () ->
registered ctxt delegate >>=? fun is_registered ->
fail_unless
is_registered
(Roll_storage.Unregistered_delegate delegate) >>=? fun () ->
Storage.Contract.Delegate.init ctxt contract delegate >>=? fun ctxt ->
link ctxt contract delegate
known ctxt delegate
>>=? fun known_delegate ->
fail_unless known_delegate (Roll_storage.Unregistered_delegate delegate)
>>=? fun () ->
registered ctxt delegate
>>=? fun is_registered ->
fail_unless is_registered (Roll_storage.Unregistered_delegate delegate)
>>=? fun () ->
Storage.Contract.Delegate.init ctxt contract delegate
>>=? fun ctxt -> link ctxt contract delegate
let get = Roll_storage.get_contract_delegate
let set c contract delegate =
match delegate with
| None -> begin
| None -> (
let delete () =
unlink c contract >>=? fun c ->
Storage.Contract.Delegate.remove c contract >>= fun c ->
return c in
unlink c contract
>>=? fun c ->
Storage.Contract.Delegate.remove c contract >>= fun c -> return c
in
match Contract_repr.is_implicit contract with
| Some pkh ->
(* check if contract is a registered delegate *)
registered c pkh >>=? fun is_registered ->
if is_registered then
fail (No_deletion pkh)
else
delete ()
| None -> delete ()
end
registered c pkh
>>=? fun is_registered ->
if is_registered then fail (No_deletion pkh) else delete ()
| None ->
delete () )
| Some delegate ->
known c delegate >>=? fun known_delegate ->
registered c delegate >>=? fun registered_delegate ->
known c delegate
>>=? fun known_delegate ->
registered c delegate
>>=? fun registered_delegate ->
let self_delegation =
match Contract_repr.is_implicit contract with
| Some pkh -> Signature.Public_key_hash.equal pkh delegate
| None -> false in
if not known_delegate || not (registered_delegate || self_delegation) then
fail (Roll_storage.Unregistered_delegate delegate)
else
begin
Storage.Contract.Delegate.get_option c contract >>=? function
| Some current_delegate
when Signature.Public_key_hash.equal delegate current_delegate ->
if self_delegation then
Roll_storage.Delegate.is_inactive c delegate >>=? function
| true -> return_unit
| false -> fail Active_delegate
else
fail Current_delegate
| None | Some _ -> return_unit
end >>=? fun () ->
(* check if contract is a registered delegate *)
begin
match Contract_repr.is_implicit contract with
| Some pkh ->
registered c pkh >>=? fun is_registered ->
(* allow self-delegation to re-activate *)
if not self_delegation && is_registered then
fail (No_deletion pkh)
else
return_unit
Signature.Public_key_hash.equal pkh delegate
| None ->
return_unit
end >>=? fun () ->
Storage.Contract.Balance.mem c contract >>= fun exists ->
false
in
if (not known_delegate) || not (registered_delegate || self_delegation)
then fail (Roll_storage.Unregistered_delegate delegate)
else
Storage.Contract.Delegate.get_option c contract
>>=? (function
| Some current_delegate
when Signature.Public_key_hash.equal delegate current_delegate
->
if self_delegation then
Roll_storage.Delegate.is_inactive c delegate
>>=? function
| true -> return_unit | false -> fail Active_delegate
else fail Current_delegate
| None | Some _ ->
return_unit)
>>=? fun () ->
(* check if contract is a registered delegate *)
( match Contract_repr.is_implicit contract with
| Some pkh ->
registered c pkh
>>=? fun is_registered ->
(* allow self-delegation to re-activate *)
if (not self_delegation) && is_registered then
fail (No_deletion pkh)
else return_unit
| None ->
return_unit )
>>=? fun () ->
Storage.Contract.Balance.mem c contract
>>= fun exists ->
fail_when
(self_delegation && not exists)
(Empty_delegate_account delegate) >>=? fun () ->
unlink c contract >>=? fun c ->
Storage.Contract.Delegate.init_set c contract delegate >>= fun c ->
link c contract delegate >>=? fun c ->
begin
if self_delegation then
Storage.Delegates.add c delegate >>= fun c ->
Roll_storage.Delegate.set_active c delegate >>=? fun c ->
return c
else
return c
end >>=? fun c ->
return c
(Empty_delegate_account delegate)
>>=? fun () ->
unlink c contract
>>=? fun c ->
Storage.Contract.Delegate.init_set c contract delegate
>>= fun c ->
link c contract delegate
>>=? fun c ->
( if self_delegation then
Storage.Delegates.add c delegate
>>= fun c ->
Roll_storage.Delegate.set_active c delegate >>=? fun c -> return c
else return c )
>>=? fun c -> return c
let remove ctxt contract =
unlink ctxt contract
let remove ctxt contract = unlink ctxt contract
let delegated_contracts ctxt delegate =
let contract = Contract_repr.implicit_contract delegate in
Storage.Contract.Delegated.elements (ctxt, contract)
let get_frozen_deposit ctxt contract cycle =
Storage.Contract.Frozen_deposits.get_option (ctxt, contract) cycle >>=? function
| None -> return Tez_repr.zero
| Some frozen -> return frozen
Storage.Contract.Frozen_deposits.get_option (ctxt, contract) cycle
>>=? function None -> return Tez_repr.zero | Some frozen -> return frozen
let credit_frozen_deposit ctxt delegate cycle amount =
let contract = Contract_repr.implicit_contract delegate in
get_frozen_deposit ctxt contract cycle >>=? fun old_amount ->
Lwt.return Tez_repr.(old_amount +? amount) >>=? fun new_amount ->
Storage.Contract.Frozen_deposits.init_set
(ctxt, contract) cycle new_amount >>= fun ctxt ->
Storage.Delegates_with_frozen_balance.add (ctxt, cycle) delegate >>= fun ctxt ->
return ctxt
get_frozen_deposit ctxt contract cycle
>>=? fun old_amount ->
Lwt.return Tez_repr.(old_amount +? amount)
>>=? fun new_amount ->
Storage.Contract.Frozen_deposits.init_set (ctxt, contract) cycle new_amount
>>= fun ctxt ->
Storage.Delegates_with_frozen_balance.add (ctxt, cycle) delegate
>>= fun ctxt -> return ctxt
let freeze_deposit ctxt delegate amount =
let {Level_repr.cycle; _} = Level_storage.current ctxt in
Roll_storage.Delegate.set_active ctxt delegate >>=? fun ctxt ->
Roll_storage.Delegate.set_active ctxt delegate
>>=? fun ctxt ->
let contract = Contract_repr.implicit_contract delegate in
Storage.Contract.Balance.get ctxt contract >>=? fun balance ->
Storage.Contract.Balance.get ctxt contract
>>=? fun balance ->
Lwt.return
(record_trace (Balance_too_low_for_deposit { delegate; deposit = amount; balance })
Tez_repr.(balance -? amount)) >>=? fun new_balance ->
Storage.Contract.Balance.set ctxt contract new_balance >>=? fun ctxt ->
credit_frozen_deposit ctxt delegate cycle amount
(record_trace
(Balance_too_low_for_deposit {delegate; deposit = amount; balance})
Tez_repr.(balance -? amount))
>>=? fun new_balance ->
Storage.Contract.Balance.set ctxt contract new_balance
>>=? fun ctxt -> credit_frozen_deposit ctxt delegate cycle amount
let get_frozen_fees ctxt contract cycle =
Storage.Contract.Frozen_fees.get_option (ctxt, contract) cycle >>=? function
| None -> return Tez_repr.zero
| Some frozen -> return frozen
Storage.Contract.Frozen_fees.get_option (ctxt, contract) cycle
>>=? function None -> return Tez_repr.zero | Some frozen -> return frozen
let credit_frozen_fees ctxt delegate cycle amount =
let contract = Contract_repr.implicit_contract delegate in
get_frozen_fees ctxt contract cycle >>=? fun old_amount ->
Lwt.return Tez_repr.(old_amount +? amount) >>=? fun new_amount ->
Storage.Contract.Frozen_fees.init_set
(ctxt, contract) cycle new_amount >>= fun ctxt ->
Storage.Delegates_with_frozen_balance.add (ctxt, cycle) delegate >>= fun ctxt ->
return ctxt
get_frozen_fees ctxt contract cycle
>>=? fun old_amount ->
Lwt.return Tez_repr.(old_amount +? amount)
>>=? fun new_amount ->
Storage.Contract.Frozen_fees.init_set (ctxt, contract) cycle new_amount
>>= fun ctxt ->
Storage.Delegates_with_frozen_balance.add (ctxt, cycle) delegate
>>= fun ctxt -> return ctxt
let freeze_fees ctxt delegate amount =
let {Level_repr.cycle; _} = Level_storage.current ctxt in
Roll_storage.Delegate.add_amount ctxt delegate amount >>=? fun ctxt ->
credit_frozen_fees ctxt delegate cycle amount
Roll_storage.Delegate.add_amount ctxt delegate amount
>>=? fun ctxt -> credit_frozen_fees ctxt delegate cycle amount
let burn_fees ctxt delegate cycle amount =
let contract = Contract_repr.implicit_contract delegate in
get_frozen_fees ctxt contract cycle >>=? fun old_amount ->
begin
match Tez_repr.(old_amount -? amount) with
get_frozen_fees ctxt contract cycle
>>=? fun old_amount ->
( match Tez_repr.(old_amount -? amount) with
| Ok new_amount ->
Roll_storage.Delegate.remove_amount
ctxt delegate amount >>=? fun ctxt ->
return (new_amount, ctxt)
Roll_storage.Delegate.remove_amount ctxt delegate amount
>>=? fun ctxt -> return (new_amount, ctxt)
| Error _ ->
Roll_storage.Delegate.remove_amount
ctxt delegate old_amount >>=? fun ctxt ->
return (Tez_repr.zero, ctxt)
end >>=? fun (new_amount, ctxt) ->
Storage.Contract.Frozen_fees.init_set (ctxt, contract) cycle new_amount >>= fun ctxt ->
return ctxt
Roll_storage.Delegate.remove_amount ctxt delegate old_amount
>>=? fun ctxt -> return (Tez_repr.zero, ctxt) )
>>=? fun (new_amount, ctxt) ->
Storage.Contract.Frozen_fees.init_set (ctxt, contract) cycle new_amount
>>= fun ctxt -> return ctxt
let get_frozen_rewards ctxt contract cycle =
Storage.Contract.Frozen_rewards.get_option (ctxt, contract) cycle >>=? function
| None -> return Tez_repr.zero
| Some frozen -> return frozen
Storage.Contract.Frozen_rewards.get_option (ctxt, contract) cycle
>>=? function None -> return Tez_repr.zero | Some frozen -> return frozen
let credit_frozen_rewards ctxt delegate cycle amount =
let contract = Contract_repr.implicit_contract delegate in
get_frozen_rewards ctxt contract cycle >>=? fun old_amount ->
Lwt.return Tez_repr.(old_amount +? amount) >>=? fun new_amount ->
Storage.Contract.Frozen_rewards.init_set
(ctxt, contract) cycle new_amount >>= fun ctxt ->
Storage.Delegates_with_frozen_balance.add (ctxt, cycle) delegate >>= fun ctxt ->
return ctxt
get_frozen_rewards ctxt contract cycle
>>=? fun old_amount ->
Lwt.return Tez_repr.(old_amount +? amount)
>>=? fun new_amount ->
Storage.Contract.Frozen_rewards.init_set (ctxt, contract) cycle new_amount
>>= fun ctxt ->
Storage.Delegates_with_frozen_balance.add (ctxt, cycle) delegate
>>= fun ctxt -> return ctxt
let freeze_rewards ctxt delegate amount =
let {Level_repr.cycle; _} = Level_storage.current ctxt in
@ -402,175 +453,224 @@ let freeze_rewards ctxt delegate amount =
let burn_rewards ctxt delegate cycle amount =
let contract = Contract_repr.implicit_contract delegate in
get_frozen_rewards ctxt contract cycle >>=? fun old_amount ->
get_frozen_rewards ctxt contract cycle
>>=? fun old_amount ->
let new_amount =
match Tez_repr.(old_amount -? amount) with
| Error _ -> Tez_repr.zero
| Ok new_amount -> new_amount in
Storage.Contract.Frozen_rewards.init_set (ctxt, contract) cycle new_amount >>= fun ctxt ->
return ctxt
| Error _ ->
Tez_repr.zero
| Ok new_amount ->
new_amount
in
Storage.Contract.Frozen_rewards.init_set (ctxt, contract) cycle new_amount
>>= fun ctxt -> return ctxt
let unfreeze ctxt delegate cycle =
let contract = Contract_repr.implicit_contract delegate in
get_frozen_deposit ctxt contract cycle >>=? fun deposit ->
get_frozen_fees ctxt contract cycle >>=? fun fees ->
get_frozen_rewards ctxt contract cycle >>=? fun rewards ->
Storage.Contract.Balance.get ctxt contract >>=? fun balance ->
Lwt.return Tez_repr.(deposit +? fees) >>=? fun unfrozen_amount ->
Lwt.return Tez_repr.(unfrozen_amount +? rewards) >>=? fun unfrozen_amount ->
Lwt.return Tez_repr.(balance +? unfrozen_amount) >>=? fun balance ->
Storage.Contract.Balance.set ctxt contract balance >>=? fun ctxt ->
Roll_storage.Delegate.add_amount ctxt delegate rewards >>=? fun ctxt ->
Storage.Contract.Frozen_deposits.remove (ctxt, contract) cycle >>= fun ctxt ->
Storage.Contract.Frozen_fees.remove (ctxt, contract) cycle >>= fun ctxt ->
Storage.Contract.Frozen_rewards.remove (ctxt, contract) cycle >>= fun ctxt ->
return (ctxt, (cleanup_balance_updates
get_frozen_deposit ctxt contract cycle
>>=? fun deposit ->
get_frozen_fees ctxt contract cycle
>>=? fun fees ->
get_frozen_rewards ctxt contract cycle
>>=? fun rewards ->
Storage.Contract.Balance.get ctxt contract
>>=? fun balance ->
Lwt.return Tez_repr.(deposit +? fees)
>>=? fun unfrozen_amount ->
Lwt.return Tez_repr.(unfrozen_amount +? rewards)
>>=? fun unfrozen_amount ->
Lwt.return Tez_repr.(balance +? unfrozen_amount)
>>=? fun balance ->
Storage.Contract.Balance.set ctxt contract balance
>>=? fun ctxt ->
Roll_storage.Delegate.add_amount ctxt delegate rewards
>>=? fun ctxt ->
Storage.Contract.Frozen_deposits.remove (ctxt, contract) cycle
>>= fun ctxt ->
Storage.Contract.Frozen_fees.remove (ctxt, contract) cycle
>>= fun ctxt ->
Storage.Contract.Frozen_rewards.remove (ctxt, contract) cycle
>>= fun ctxt ->
return
( ctxt,
cleanup_balance_updates
[ (Deposits (delegate, cycle), Debited deposit);
(Fees (delegate, cycle), Debited fees);
(Rewards (delegate, cycle), Debited rewards);
(Contract (Contract_repr.implicit_contract delegate), Credited unfrozen_amount)]))
( Contract (Contract_repr.implicit_contract delegate),
Credited unfrozen_amount ) ] )
let cycle_end ctxt last_cycle unrevealed =
let preserved = Constants_storage.preserved_cycles ctxt in
begin
match Cycle_repr.pred last_cycle with
| None -> return (ctxt,[])
( match Cycle_repr.pred last_cycle with
| None ->
return (ctxt, [])
| Some revealed_cycle ->
List.fold_left
(fun acc (u : Nonce_storage.unrevealed) ->
acc >>=? fun (ctxt, balance_updates) ->
burn_fees
ctxt u.delegate revealed_cycle u.fees >>=? fun ctxt ->
burn_rewards
ctxt u.delegate revealed_cycle u.rewards >>=? fun ctxt ->
let bus = [(Fees (u.delegate, revealed_cycle), Debited u.fees);
(Rewards (u.delegate, revealed_cycle), Debited u.rewards)] in
acc
>>=? fun (ctxt, balance_updates) ->
burn_fees ctxt u.delegate revealed_cycle u.fees
>>=? fun ctxt ->
burn_rewards ctxt u.delegate revealed_cycle u.rewards
>>=? fun ctxt ->
let bus =
[ (Fees (u.delegate, revealed_cycle), Debited u.fees);
(Rewards (u.delegate, revealed_cycle), Debited u.rewards) ]
in
return (ctxt, bus @ balance_updates))
(return (ctxt,[])) unrevealed
end >>=? fun (ctxt, balance_updates) ->
(return (ctxt, []))
unrevealed )
>>=? fun (ctxt, balance_updates) ->
match Cycle_repr.sub last_cycle preserved with
| None -> return (ctxt, balance_updates, [])
| None ->
return (ctxt, balance_updates, [])
| Some unfrozen_cycle ->
Storage.Delegates_with_frozen_balance.fold (ctxt, unfrozen_cycle)
Storage.Delegates_with_frozen_balance.fold
(ctxt, unfrozen_cycle)
~init:(Ok (ctxt, balance_updates))
~f:(fun delegate acc ->
Lwt.return acc >>=? fun (ctxt, bus) ->
unfreeze ctxt
delegate unfrozen_cycle >>=? fun (ctxt, balance_updates) ->
return (ctxt, balance_updates @ bus)) >>=? fun (ctxt, balance_updates) ->
Storage.Delegates_with_frozen_balance.clear (ctxt, unfrozen_cycle) >>= fun ctxt ->
Storage.Active_delegates_with_rolls.fold ctxt
Lwt.return acc
>>=? fun (ctxt, bus) ->
unfreeze ctxt delegate unfrozen_cycle
>>=? fun (ctxt, balance_updates) ->
return (ctxt, balance_updates @ bus))
>>=? fun (ctxt, balance_updates) ->
Storage.Delegates_with_frozen_balance.clear (ctxt, unfrozen_cycle)
>>= fun ctxt ->
Storage.Active_delegates_with_rolls.fold
ctxt
~init:(Ok (ctxt, []))
~f:(fun delegate acc ->
Lwt.return acc >>=? fun (ctxt, deactivated) ->
Storage.Contract.Delegate_desactivation.get ctxt
(Contract_repr.implicit_contract delegate) >>=? fun cycle ->
Lwt.return acc
>>=? fun (ctxt, deactivated) ->
Storage.Contract.Delegate_desactivation.get
ctxt
(Contract_repr.implicit_contract delegate)
>>=? fun cycle ->
if Cycle_repr.(cycle <= last_cycle) then
Roll_storage.Delegate.set_inactive ctxt delegate >>=? fun ctxt ->
return (ctxt, delegate :: deactivated)
else
return (ctxt, deactivated)) >>=? fun (ctxt, deactivated) ->
Roll_storage.Delegate.set_inactive ctxt delegate
>>=? fun ctxt -> return (ctxt, delegate :: deactivated)
else return (ctxt, deactivated))
>>=? fun (ctxt, deactivated) ->
return (ctxt, balance_updates, deactivated)
let punish ctxt delegate cycle =
let contract = Contract_repr.implicit_contract delegate in
get_frozen_deposit ctxt contract cycle >>=? fun deposit ->
get_frozen_fees ctxt contract cycle >>=? fun fees ->
get_frozen_rewards ctxt contract cycle >>=? fun rewards ->
Roll_storage.Delegate.remove_amount ctxt delegate deposit >>=? fun ctxt ->
Roll_storage.Delegate.remove_amount ctxt delegate fees >>=? fun ctxt ->
get_frozen_deposit ctxt contract cycle
>>=? fun deposit ->
get_frozen_fees ctxt contract cycle
>>=? fun fees ->
get_frozen_rewards ctxt contract cycle
>>=? fun rewards ->
Roll_storage.Delegate.remove_amount ctxt delegate deposit
>>=? fun ctxt ->
Roll_storage.Delegate.remove_amount ctxt delegate fees
>>=? fun ctxt ->
(* Rewards are not accounted in the delegate's rolls yet... *)
Storage.Contract.Frozen_deposits.remove (ctxt, contract) cycle >>= fun ctxt ->
Storage.Contract.Frozen_fees.remove (ctxt, contract) cycle >>= fun ctxt ->
Storage.Contract.Frozen_rewards.remove (ctxt, contract) cycle >>= fun ctxt ->
return (ctxt, { deposit ; fees ; rewards })
Storage.Contract.Frozen_deposits.remove (ctxt, contract) cycle
>>= fun ctxt ->
Storage.Contract.Frozen_fees.remove (ctxt, contract) cycle
>>= fun ctxt ->
Storage.Contract.Frozen_rewards.remove (ctxt, contract) cycle
>>= fun ctxt -> return (ctxt, {deposit; fees; rewards})
let has_frozen_balance ctxt delegate cycle =
let contract = Contract_repr.implicit_contract delegate in
get_frozen_deposit ctxt contract cycle >>=? fun deposit ->
get_frozen_deposit ctxt contract cycle
>>=? fun deposit ->
if Tez_repr.(deposit <> zero) then return_true
else
get_frozen_fees ctxt contract cycle >>=? fun fees ->
get_frozen_fees ctxt contract cycle
>>=? fun fees ->
if Tez_repr.(fees <> zero) then return_true
else
get_frozen_rewards ctxt contract cycle >>=? fun rewards ->
return Tez_repr.(rewards <> zero)
get_frozen_rewards ctxt contract cycle
>>=? fun rewards -> return Tez_repr.(rewards <> zero)
let frozen_balance_by_cycle_encoding =
let open Data_encoding in
conv
(Cycle_repr.Map.bindings)
Cycle_repr.Map.bindings
(List.fold_left
(fun m (c, b) -> Cycle_repr.Map.add c b m)
Cycle_repr.Map.empty)
(list (merge_objs
(list
(merge_objs
(obj1 (req "cycle" Cycle_repr.encoding))
frozen_balance_encoding))
let empty_frozen_balance =
{ deposit = Tez_repr.zero ;
fees = Tez_repr.zero ;
rewards = Tez_repr.zero }
{deposit = Tez_repr.zero; fees = Tez_repr.zero; rewards = Tez_repr.zero}
let frozen_balance_by_cycle ctxt delegate =
let contract = Contract_repr.implicit_contract delegate in
let map = Cycle_repr.Map.empty in
Storage.Contract.Frozen_deposits.fold
(ctxt, contract) ~init:map
(ctxt, contract)
~init:map
~f:(fun cycle amount map ->
Lwt.return
(Cycle_repr.Map.add cycle
{ empty_frozen_balance with deposit = amount } map)) >>= fun map ->
(Cycle_repr.Map.add
cycle
{empty_frozen_balance with deposit = amount}
map))
>>= fun map ->
Storage.Contract.Frozen_fees.fold
(ctxt, contract) ~init:map
(ctxt, contract)
~init:map
~f:(fun cycle amount map ->
let balance =
match Cycle_repr.Map.find_opt cycle map with
| None -> empty_frozen_balance
| Some balance -> balance in
Lwt.return
(Cycle_repr.Map.add cycle
{ balance with fees = amount } map)) >>= fun map ->
| None ->
empty_frozen_balance
| Some balance ->
balance
in
Lwt.return (Cycle_repr.Map.add cycle {balance with fees = amount} map))
>>= fun map ->
Storage.Contract.Frozen_rewards.fold
(ctxt, contract) ~init:map
(ctxt, contract)
~init:map
~f:(fun cycle amount map ->
let balance =
match Cycle_repr.Map.find_opt cycle map with
| None -> empty_frozen_balance
| Some balance -> balance in
Lwt.return
(Cycle_repr.Map.add cycle
{ balance with rewards = amount } map)) >>= fun map ->
Lwt.return map
| None ->
empty_frozen_balance
| Some balance ->
balance
in
Lwt.return (Cycle_repr.Map.add cycle {balance with rewards = amount} map))
>>= fun map -> Lwt.return map
let frozen_balance ctxt delegate =
let contract = Contract_repr.implicit_contract delegate in
let balance = Ok Tez_repr.zero in
Storage.Contract.Frozen_deposits.fold
(ctxt, contract) ~init:balance
(ctxt, contract)
~init:balance
~f:(fun _cycle amount acc ->
Lwt.return acc >>=? fun acc ->
Lwt.return (Tez_repr.(acc +? amount))) >>= fun balance ->
Lwt.return acc >>=? fun acc -> Lwt.return Tez_repr.(acc +? amount))
>>= fun balance ->
Storage.Contract.Frozen_fees.fold
(ctxt, contract) ~init:balance
(ctxt, contract)
~init:balance
~f:(fun _cycle amount acc ->
Lwt.return acc >>=? fun acc ->
Lwt.return (Tez_repr.(acc +? amount))) >>= fun balance ->
Lwt.return acc >>=? fun acc -> Lwt.return Tez_repr.(acc +? amount))
>>= fun balance ->
Storage.Contract.Frozen_rewards.fold
(ctxt, contract) ~init:balance
(ctxt, contract)
~init:balance
~f:(fun _cycle amount acc ->
Lwt.return acc >>=? fun acc ->
Lwt.return (Tez_repr.(acc +? amount))) >>= fun balance ->
Lwt.return balance
Lwt.return acc >>=? fun acc -> Lwt.return Tez_repr.(acc +? amount))
>>= fun balance -> Lwt.return balance
let full_balance ctxt delegate =
let contract = Contract_repr.implicit_contract delegate in
frozen_balance ctxt delegate >>=? fun frozen_balance ->
Storage.Contract.Balance.get ctxt contract >>=? fun balance ->
Lwt.return Tez_repr.(frozen_balance +? balance)
frozen_balance ctxt delegate
>>=? fun frozen_balance ->
Storage.Contract.Balance.get ctxt contract
>>=? fun balance -> Lwt.return Tez_repr.(frozen_balance +? balance)
let deactivated = Roll_storage.Delegate.is_inactive
@ -580,27 +680,34 @@ let grace_period ctxt delegate =
let staking_balance ctxt delegate =
let token_per_rolls = Constants_storage.tokens_per_roll ctxt in
Roll_storage.get_rolls ctxt delegate >>=? fun rolls ->
Roll_storage.get_change ctxt delegate >>=? fun change ->
Roll_storage.get_rolls ctxt delegate
>>=? fun rolls ->
Roll_storage.get_change ctxt delegate
>>=? fun change ->
let rolls = Int64.of_int (List.length rolls) in
Lwt.return Tez_repr.(token_per_rolls *? rolls) >>=? fun balance ->
Lwt.return Tez_repr.(balance +? change)
Lwt.return Tez_repr.(token_per_rolls *? rolls)
>>=? fun balance -> Lwt.return Tez_repr.(balance +? change)
let delegated_balance ctxt delegate =
let contract = Contract_repr.implicit_contract delegate in
staking_balance ctxt delegate >>=? fun staking_balance ->
Storage.Contract.Balance.get ctxt contract >>= fun self_staking_balance ->
staking_balance ctxt delegate
>>=? fun staking_balance ->
Storage.Contract.Balance.get ctxt contract
>>= fun self_staking_balance ->
Storage.Contract.Frozen_deposits.fold
(ctxt, contract) ~init:self_staking_balance
(ctxt, contract)
~init:self_staking_balance
~f:(fun _cycle amount acc ->
Lwt.return acc >>=? fun acc ->
Lwt.return (Tez_repr.(acc +? amount))) >>= fun self_staking_balance ->
Lwt.return acc >>=? fun acc -> Lwt.return Tez_repr.(acc +? amount))
>>= fun self_staking_balance ->
Storage.Contract.Frozen_fees.fold
(ctxt, contract) ~init:self_staking_balance
(ctxt, contract)
~init:self_staking_balance
~f:(fun _cycle amount acc ->
Lwt.return acc >>=? fun acc ->
Lwt.return (Tez_repr.(acc +? amount))) >>=? fun self_staking_balance ->
Lwt.return acc >>=? fun acc -> Lwt.return Tez_repr.(acc +? amount))
>>=? fun self_staking_balance ->
Lwt.return Tez_repr.(staking_balance -? self_staking_balance)
let fold = Storage.Delegates.fold
let list = Storage.Delegates.elements

View File

@ -31,9 +31,7 @@ type balance =
| Deposits of Signature.Public_key_hash.t * Cycle_repr.t
(** A credit or debit of tezzies to a balance. *)
type balance_update =
| Debited of Tez_repr.t
| Credited of Tez_repr.t
type balance_update = Debited of Tez_repr.t | Credited of Tez_repr.t
(** A list of balance updates. Duplicates may happen. *)
type balance_updates = (balance * balance_update) list
@ -51,19 +49,22 @@ type frozen_balance = {
(** Allow to register a delegate when creating an account. *)
val init :
Raw_context.t -> Contract_repr.t -> Signature.Public_key_hash.t ->
Raw_context.t ->
Contract_repr.t ->
Signature.Public_key_hash.t ->
Raw_context.t tzresult Lwt.t
(** Cleanup delegation when deleting a contract. *)
val remove:
Raw_context.t -> Contract_repr.t -> Raw_context.t tzresult Lwt.t
val remove : Raw_context.t -> Contract_repr.t -> Raw_context.t tzresult Lwt.t
(** Reading the current delegate of a contract. *)
val get :
Raw_context.t -> Contract_repr.t ->
Raw_context.t ->
Contract_repr.t ->
Signature.Public_key_hash.t option tzresult Lwt.t
val registered: Raw_context.t -> Signature.Public_key_hash.t -> bool tzresult Lwt.t
val registered :
Raw_context.t -> Signature.Public_key_hash.t -> bool tzresult Lwt.t
(** Updating the delegate of a contract.
@ -72,7 +73,9 @@ val registered: Raw_context.t -> Signature.Public_key_hash.t -> bool tzresult Lw
cannot unregister a delegate for now. The associate contract is now
'undeletable'. *)
val set :
Raw_context.t -> Contract_repr.t -> Signature.Public_key_hash.t option ->
Raw_context.t ->
Contract_repr.t ->
Signature.Public_key_hash.t option ->
Raw_context.t tzresult Lwt.t
type error +=
@ -80,16 +83,20 @@ type error +=
| Active_delegate (* `Temporary *)
| Current_delegate (* `Temporary *)
| Empty_delegate_account of Signature.Public_key_hash.t (* `Temporary *)
| Balance_too_low_for_deposit of
{ delegate : Signature.Public_key_hash.t ;
| Balance_too_low_for_deposit of {
delegate : Signature.Public_key_hash.t;
deposit : Tez_repr.t;
balance : Tez_repr.t } (* `Temporary *)
balance : Tez_repr.t;
}
(* `Temporary *)
(** Iterate on all registered delegates. *)
val fold :
Raw_context.t ->
init:'a ->
f:(Signature.Public_key_hash.t -> 'a -> 'a Lwt.t) -> 'a Lwt.t
f:(Signature.Public_key_hash.t -> 'a -> 'a Lwt.t) ->
'a Lwt.t
(** List all registered delegates. *)
val list : Raw_context.t -> Signature.Public_key_hash.t list Lwt.t
@ -99,15 +106,21 @@ val list: Raw_context.t -> Signature.Public_key_hash.t list Lwt.t
allocation. Rewards won't trigger new rolls allocation until
unfrozen. *)
val freeze_deposit :
Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t ->
Raw_context.t ->
Signature.Public_key_hash.t ->
Tez_repr.t ->
Raw_context.t tzresult Lwt.t
val freeze_fees :
Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t ->
Raw_context.t ->
Signature.Public_key_hash.t ->
Tez_repr.t ->
Raw_context.t tzresult Lwt.t
val freeze_rewards :
Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t ->
Raw_context.t ->
Signature.Public_key_hash.t ->
Tez_repr.t ->
Raw_context.t tzresult Lwt.t
(** Trigger the context maintenance at the end of cycle 'n', i.e.:
@ -116,27 +129,34 @@ val freeze_rewards:
Returns a list of account with the amount that was unfrozen for each
and the list of deactivated delegates. *)
val cycle_end :
Raw_context.t -> Cycle_repr.t -> Nonce_storage.unrevealed list ->
(Raw_context.t * balance_updates * Signature.Public_key_hash.t list) tzresult Lwt.t
Raw_context.t ->
Cycle_repr.t ->
Nonce_storage.unrevealed list ->
(Raw_context.t * balance_updates * Signature.Public_key_hash.t list) tzresult
Lwt.t
(** Burn all then frozen deposit/fees/rewards for a delegate at a given
cycle. Returns the burned amounts. *)
val punish :
Raw_context.t -> Signature.Public_key_hash.t -> Cycle_repr.t ->
Raw_context.t ->
Signature.Public_key_hash.t ->
Cycle_repr.t ->
(Raw_context.t * frozen_balance) tzresult Lwt.t
(** Has the given key some frozen tokens in its implicit contract? *)
val has_frozen_balance :
Raw_context.t -> Signature.Public_key_hash.t -> Cycle_repr.t ->
Raw_context.t ->
Signature.Public_key_hash.t ->
Cycle_repr.t ->
bool tzresult Lwt.t
(** Returns the amount of frozen deposit, fees and rewards associated
to a given delegate. *)
val frozen_balance :
Raw_context.t -> Signature.Public_key_hash.t ->
Tez_repr.t tzresult Lwt.t
Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t
val frozen_balance_encoding : frozen_balance Data_encoding.t
val frozen_balance_by_cycle_encoding :
frozen_balance Cycle_repr.Map.t Data_encoding.t
@ -144,33 +164,28 @@ val frozen_balance_by_cycle_encoding:
to a given delegate, indexed by the cycle by which at the end the
balance will be unfrozen. *)
val frozen_balance_by_cycle :
Raw_context.t -> Signature.Public_key_hash.t ->
Raw_context.t ->
Signature.Public_key_hash.t ->
frozen_balance Cycle_repr.Map.t Lwt.t
(** Returns the full 'balance' of the implicit contract associated to
a given key, i.e. the sum of the spendable balance and of the
frozen balance. *)
val full_balance :
Raw_context.t -> Signature.Public_key_hash.t ->
Tez_repr.t tzresult Lwt.t
Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t
val staking_balance :
Raw_context.t -> Signature.Public_key_hash.t ->
Tez_repr.t tzresult Lwt.t
Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t
(** Returns the list of contracts (implicit or originated) that delegated towards a given delegate *)
val delegated_contracts :
Raw_context.t -> Signature.Public_key_hash.t ->
Contract_repr.t list Lwt.t
Raw_context.t -> Signature.Public_key_hash.t -> Contract_repr.t list Lwt.t
val delegated_balance :
Raw_context.t -> Signature.Public_key_hash.t ->
Tez_repr.t tzresult Lwt.t
Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t
val deactivated :
Raw_context.t -> Signature.Public_key_hash.t ->
bool tzresult Lwt.t
Raw_context.t -> Signature.Public_key_hash.t -> bool tzresult Lwt.t
val grace_period :
Raw_context.t -> Signature.Public_key_hash.t ->
Cycle_repr.t tzresult Lwt.t
Raw_context.t -> Signature.Public_key_hash.t -> Cycle_repr.t tzresult Lwt.t

View File

@ -1,2 +1,2 @@
(lang dune 1.11)
(name tezos-embedded-protocol-005-PsBabyM1)
(name tezos-embedded-protocol-006-PsCARTHA)

View File

@ -11,7 +11,7 @@
(targets environment.ml)
(action
(write-file %{targets}
"module Name = struct let name = \"005-PsBabyM1\" end
"module Name = struct let name = \"006-PsCARTHA\" end
include Tezos_protocol_environment.MakeV1(Name)()
module CamlinternalFormatBasics = struct include CamlinternalFormatBasics end
")))
@ -22,7 +22,7 @@ module CamlinternalFormatBasics = struct include CamlinternalFormatBasics end
(:src_dir TEZOS_PROTOCOL))
(action
(with-stdout-to %{targets}
(chdir %{workspace_root} (run %{bin:tezos-embedded-protocol-packer} "%{src_dir}" "005_PsBabyM1")))))
(chdir %{workspace_root} (run %{bin:tezos-embedded-protocol-packer} "%{src_dir}" "006_PsCARTHA")))))
(rule
(targets functor.ml)
@ -37,67 +37,67 @@ module CamlinternalFormatBasics = struct include CamlinternalFormatBasics end
(deps misc.mli misc.ml storage_description.mli storage_description.ml state_hash.ml nonce_hash.ml script_expr_hash.ml contract_hash.ml blinded_public_key_hash.mli blinded_public_key_hash.ml qty_repr.ml tez_repr.mli tez_repr.ml period_repr.mli period_repr.ml time_repr.mli time_repr.ml constants_repr.ml fitness_repr.ml raw_level_repr.mli raw_level_repr.ml voting_period_repr.mli voting_period_repr.ml cycle_repr.mli cycle_repr.ml level_repr.mli level_repr.ml seed_repr.mli seed_repr.ml gas_limit_repr.mli gas_limit_repr.ml script_int_repr.mli script_int_repr.ml script_timestamp_repr.mli script_timestamp_repr.ml michelson_v1_primitives.mli michelson_v1_primitives.ml script_repr.mli script_repr.ml legacy_script_support_repr.mli legacy_script_support_repr.ml contract_repr.mli contract_repr.ml roll_repr.mli roll_repr.ml vote_repr.mli vote_repr.ml block_header_repr.mli block_header_repr.ml operation_repr.mli operation_repr.ml manager_repr.mli manager_repr.ml commitment_repr.mli commitment_repr.ml parameters_repr.mli parameters_repr.ml raw_context.mli raw_context.ml storage_sigs.ml storage_functors.mli storage_functors.ml storage.mli storage.ml constants_storage.ml level_storage.mli level_storage.ml nonce_storage.mli nonce_storage.ml seed_storage.mli seed_storage.ml roll_storage.mli roll_storage.ml delegate_storage.mli delegate_storage.ml contract_storage.mli contract_storage.ml bootstrap_storage.mli bootstrap_storage.ml fitness_storage.ml vote_storage.mli vote_storage.ml commitment_storage.mli commitment_storage.ml init_storage.ml fees_storage.mli fees_storage.ml alpha_context.mli alpha_context.ml script_typed_ir.ml script_tc_errors.ml michelson_v1_gas.mli michelson_v1_gas.ml script_ir_annot.mli script_ir_annot.ml script_ir_translator.mli script_ir_translator.ml script_tc_errors_registration.ml script_interpreter.mli script_interpreter.ml baking.mli baking.ml amendment.mli amendment.ml apply_results.mli apply_results.ml apply.ml services_registration.ml constants_services.mli constants_services.ml contract_services.mli contract_services.ml delegate_services.mli delegate_services.ml helpers_services.mli helpers_services.ml voting_services.mli voting_services.ml alpha_services.mli alpha_services.ml main.mli main.ml)
(action
(write-file %{targets}
"module Environment = Tezos_protocol_environment_005_PsBabyM1.Environment
let hash = Tezos_crypto.Protocol_hash.of_b58check_exn \"PsBabyM1eUXZseaJdmXFApDSBqj8YBfwELoxZHHW77EMcAbbwAS\"
"module Environment = Tezos_protocol_environment_006_PsCARTHA.Environment
let hash = Tezos_crypto.Protocol_hash.of_b58check_exn \"PsCARTHAGazKbHtnKfLzQg3kms52kSRpgnDY982a9oYsSXRLQEb\"
let name = Environment.Name.name
include Tezos_raw_protocol_005_PsBabyM1
include Tezos_raw_protocol_005_PsBabyM1.Main
include Tezos_raw_protocol_006_PsCARTHA
include Tezos_raw_protocol_006_PsCARTHA.Main
")))
(library
(name tezos_protocol_environment_005_PsBabyM1)
(public_name tezos-protocol-005-PsBabyM1.environment)
(name tezos_protocol_environment_006_PsCARTHA)
(public_name tezos-protocol-006-PsCARTHA.environment)
(library_flags (:standard -linkall))
(libraries tezos-protocol-environment)
(modules Environment))
(library
(name tezos_raw_protocol_005_PsBabyM1)
(public_name tezos-protocol-005-PsBabyM1.raw)
(libraries tezos_protocol_environment_005_PsBabyM1)
(name tezos_raw_protocol_006_PsCARTHA)
(public_name tezos-protocol-006-PsCARTHA.raw)
(libraries tezos_protocol_environment_006_PsCARTHA)
(library_flags (:standard -linkall))
(flags (:standard -nopervasives -nostdlib
-w +a-4-6-7-9-29-32-40..42-44-45-48
-warn-error -a+8
-open Tezos_protocol_environment_005_PsBabyM1__Environment
-open Tezos_protocol_environment_006_PsCARTHA__Environment
-open Pervasives
-open Error_monad))
(modules Misc Storage_description State_hash Nonce_hash Script_expr_hash Contract_hash Blinded_public_key_hash Qty_repr Tez_repr Period_repr Time_repr Constants_repr Fitness_repr Raw_level_repr Voting_period_repr Cycle_repr Level_repr Seed_repr Gas_limit_repr Script_int_repr Script_timestamp_repr Michelson_v1_primitives Script_repr Legacy_script_support_repr Contract_repr Roll_repr Vote_repr Block_header_repr Operation_repr Manager_repr Commitment_repr Parameters_repr Raw_context Storage_sigs Storage_functors Storage Constants_storage Level_storage Nonce_storage Seed_storage Roll_storage Delegate_storage Contract_storage Bootstrap_storage Fitness_storage Vote_storage Commitment_storage Init_storage Fees_storage Alpha_context Script_typed_ir Script_tc_errors Michelson_v1_gas Script_ir_annot Script_ir_translator Script_tc_errors_registration Script_interpreter Baking Amendment Apply_results Apply Services_registration Constants_services Contract_services Delegate_services Helpers_services Voting_services Alpha_services Main))
(install
(section lib)
(package tezos-protocol-005-PsBabyM1)
(package tezos-protocol-006-PsCARTHA)
(files (TEZOS_PROTOCOL as raw/TEZOS_PROTOCOL)))
(library
(name tezos_protocol_005_PsBabyM1)
(public_name tezos-protocol-005-PsBabyM1)
(name tezos_protocol_006_PsCARTHA)
(public_name tezos-protocol-006-PsCARTHA)
(libraries
tezos-protocol-environment
tezos-protocol-environment-sigs
tezos_raw_protocol_005_PsBabyM1)
tezos_raw_protocol_006_PsCARTHA)
(flags -w "+a-4-6-7-9-29-40..42-44-45-48"
-warn-error "-a+8"
-nopervasives)
(modules Protocol))
(library
(name tezos_protocol_005_PsBabyM1_functor)
(public_name tezos-protocol-005-PsBabyM1.functor)
(name tezos_protocol_006_PsCARTHA_functor)
(public_name tezos-protocol-006-PsCARTHA.functor)
(libraries
tezos-protocol-environment
tezos-protocol-environment-sigs
tezos_raw_protocol_005_PsBabyM1)
tezos_raw_protocol_006_PsCARTHA)
(flags -w "+a-4-6-7-9-29-40..42-44-45-48"
-warn-error "-a+8"
-nopervasives)
(modules Functor))
(library
(name tezos_embedded_protocol_005_PsBabyM1)
(public_name tezos-embedded-protocol-005-PsBabyM1)
(name tezos_embedded_protocol_006_PsCARTHA)
(public_name tezos-embedded-protocol-006-PsCARTHA)
(library_flags (:standard -linkall))
(libraries tezos-protocol-005-PsBabyM1
(libraries tezos-protocol-006-PsCARTHA
tezos-protocol-updater
tezos-protocol-environment)
(flags (:standard -w +a-4-6-7-9-29-32-40..42-44-45-48
@ -106,4 +106,4 @@ include Tezos_raw_protocol_005_PsBabyM1.Main
(alias
(name runtest_sandbox)
(deps .tezos_protocol_005_PsBabyM1.objs/native/tezos_protocol_005_PsBabyM1.cmx))
(deps .tezos_protocol_006_PsCARTHA.objs/native/tezos_protocol_006_PsCARTHA.cmx))

View File

@ -24,7 +24,9 @@
(*****************************************************************************)
type error += Cannot_pay_storage_fee (* `Temporary *)
type error += Operation_quota_exceeded (* `Temporary *)
type error += Storage_limit_too_high (* `Permanent *)
let () =
@ -43,8 +45,8 @@ let () =
~id:"storage_exhausted.operation"
~title:"Storage quota exceeded for the operation"
~description:
"A script or one of its callee wrote more \
bytes than the operation said it would"
"A script or one of its callee wrote more bytes than the operation said \
it would"
Data_encoding.empty
(function Operation_quota_exceeded -> Some () | _ -> None)
(fun () -> Operation_quota_exceeded) ;
@ -52,8 +54,7 @@ let () =
`Permanent
~id:"storage_limit_too_high"
~title:"Storage limit out of protocol hard bounds"
~description:
"A transaction tried to exceed the hard limit on storage"
~description:"A transaction tried to exceed the hard limit on storage"
empty
(function Storage_limit_too_high -> Some () | _ -> None)
(fun () -> Storage_limit_too_high)
@ -62,50 +63,59 @@ let origination_burn c =
let origination_size = Constants_storage.origination_size c in
let cost_per_byte = Constants_storage.cost_per_byte c in
(* the origination burn, measured in bytes *)
Lwt.return
Tez_repr.(cost_per_byte *? (Int64.of_int origination_size)) >>=? fun to_be_paid ->
return (Raw_context.update_allocated_contracts_count c,
to_be_paid)
Lwt.return Tez_repr.(cost_per_byte *? Int64.of_int origination_size)
>>=? fun to_be_paid ->
return (Raw_context.update_allocated_contracts_count c, to_be_paid)
let record_paid_storage_space c contract =
Contract_storage.used_storage_space c contract >>=? fun size ->
Contract_storage.set_paid_storage_space_and_return_fees_to_pay c contract size >>=? fun (to_be_paid, c) ->
Contract_storage.used_storage_space c contract
>>=? fun size ->
Contract_storage.set_paid_storage_space_and_return_fees_to_pay
c
contract
size
>>=? fun (to_be_paid, c) ->
let c = Raw_context.update_storage_space_to_pay c to_be_paid in
let cost_per_byte = Constants_storage.cost_per_byte c in
Lwt.return (Tez_repr.(cost_per_byte *? (Z.to_int64 to_be_paid))) >>=? fun to_burn ->
return (c, size, to_be_paid, to_burn)
Lwt.return Tez_repr.(cost_per_byte *? Z.to_int64 to_be_paid)
>>=? fun to_burn -> return (c, size, to_be_paid, to_burn)
let burn_storage_fees c ~storage_limit ~payer =
let origination_size = Constants_storage.origination_size c in
let c, storage_space_to_pay, allocated_contracts =
Raw_context.clear_storage_space_to_pay c in
let (c, storage_space_to_pay, allocated_contracts) =
Raw_context.clear_storage_space_to_pay c
in
let storage_space_for_allocated_contracts =
Z.mul (Z.of_int allocated_contracts) (Z.of_int origination_size) in
Z.mul (Z.of_int allocated_contracts) (Z.of_int origination_size)
in
let consumed =
Z.add storage_space_to_pay storage_space_for_allocated_contracts in
Z.add storage_space_to_pay storage_space_for_allocated_contracts
in
let remaining = Z.sub storage_limit consumed in
if Compare.Z.(remaining < Z.zero) then
fail Operation_quota_exceeded
if Compare.Z.(remaining < Z.zero) then fail Operation_quota_exceeded
else
let cost_per_byte = Constants_storage.cost_per_byte c in
Lwt.return (Tez_repr.(cost_per_byte *? (Z.to_int64 consumed))) >>=? fun to_burn ->
Lwt.return Tez_repr.(cost_per_byte *? Z.to_int64 consumed)
>>=? fun to_burn ->
(* Burning the fees... *)
if Tez_repr.(to_burn = Tez_repr.zero) then
(* If the payer was was deleted by transfering all its balance, and no space was used,
burning zero would fail *)
return c
else
trace Cannot_pay_storage_fee
(Contract_storage.must_exist c payer >>=? fun () ->
Contract_storage.spend c payer to_burn) >>=? fun c ->
return c
trace
Cannot_pay_storage_fee
( Contract_storage.must_exist c payer
>>=? fun () -> Contract_storage.spend c payer to_burn )
>>=? fun c -> return c
let check_storage_limit c ~storage_limit =
if Compare.Z.(storage_limit > (Raw_context.constants c).hard_storage_limit_per_operation)
|| Compare.Z.(storage_limit < Z.zero)then
error Storage_limit_too_high
else
ok ()
if
Compare.Z.(
storage_limit
> (Raw_context.constants c).hard_storage_limit_per_operation)
|| Compare.Z.(storage_limit < Z.zero)
then error Storage_limit_too_high
else ok ()
let start_counting_storage_fees c =
Raw_context.init_storage_space_to_pay c
let start_counting_storage_fees c = Raw_context.init_storage_space_to_pay c

View File

@ -24,7 +24,9 @@
(*****************************************************************************)
type error += Cannot_pay_storage_fee (* `Temporary *)
type error += Operation_quota_exceeded (* `Temporary *)
type error += Storage_limit_too_high (* `Permanent *)
(** Does not burn, only adds the burn to storage space to be paid *)
@ -33,14 +35,16 @@ val origination_burn:
(** The returned Tez quantity is for logging purpose only *)
val record_paid_storage_space :
Raw_context.t -> Contract_repr.t ->
Raw_context.t ->
Contract_repr.t ->
(Raw_context.t * Z.t * Z.t * Tez_repr.t) tzresult Lwt.t
val check_storage_limit:
Raw_context.t -> storage_limit:Z.t -> unit tzresult
val check_storage_limit : Raw_context.t -> storage_limit:Z.t -> unit tzresult
val start_counting_storage_fees :
Raw_context.t -> Raw_context.t
val start_counting_storage_fees : Raw_context.t -> Raw_context.t
val burn_storage_fees :
Raw_context.t -> storage_limit:Z.t -> payer:Contract_repr.t -> Raw_context.t tzresult Lwt.t
Raw_context.t ->
storage_limit:Z.t ->
payer:Contract_repr.t ->
Raw_context.t tzresult Lwt.t

View File

@ -38,29 +38,25 @@ let () =
let int64_to_bytes i =
let b = MBytes.create 8 in
MBytes.set_int64 b 0 i;
b
MBytes.set_int64 b 0 i ; b
let int64_of_bytes b =
if Compare.Int.(MBytes.length b <> 8) then
error Invalid_fitness
else
ok (MBytes.get_int64 b 0)
if Compare.Int.(MBytes.length b <> 8) then error Invalid_fitness
else ok (MBytes.get_int64 b 0)
let from_int64 fitness =
[ MBytes.of_string Constants_repr.version_number ;
int64_to_bytes fitness ]
[MBytes.of_string Constants_repr.version_number; int64_to_bytes fitness]
let to_int64 = function
| [ version ;
fitness ]
when Compare.String.
(MBytes.to_string version = Constants_repr.version_number) ->
| [version; fitness]
when Compare.String.(
MBytes.to_string version = Constants_repr.version_number) ->
int64_of_bytes fitness
| [ version ;
_fitness (* ignored since higher version takes priority *) ]
when Compare.String.
(MBytes.to_string version = Constants_repr.version_number_004) ->
| [version; _fitness (* ignored since higher version takes priority *)]
when Compare.String.(
MBytes.to_string version = Constants_repr.version_number_004) ->
ok 0L
| [] -> ok 0L
| _ -> error Invalid_fitness
| [] ->
ok 0L
| _ ->
error Invalid_fitness

View File

@ -24,6 +24,7 @@
(*****************************************************************************)
let current = Raw_context.current_fitness
let increase ?(gap = 1) ctxt =
let fitness = current ctxt in
Raw_context.set_current_fitness ctxt (Int64.add (Int64.of_int gap) fitness)

View File

@ -23,29 +23,30 @@
(* *)
(*****************************************************************************)
type t =
| Unaccounted
| Limited of { remaining : Z.t }
type t = Unaccounted | Limited of {remaining : Z.t}
type internal_gas = Z.t
type cost =
{ allocations : Z.t ;
type cost = {
allocations : Z.t;
steps : Z.t;
reads : Z.t;
writes : Z.t;
bytes_read : Z.t;
bytes_written : Z.t }
bytes_written : Z.t;
}
let encoding =
let open Data_encoding in
union
[ case (Tag 0)
[ case
(Tag 0)
~title:"Limited"
z
(function Limited {remaining} -> Some remaining | _ -> None)
(fun remaining -> Limited {remaining});
case (Tag 1)
case
(Tag 1)
~title:"Unaccounted"
(constant "unaccounted")
(function Unaccounted -> Some () | _ -> None)
@ -72,8 +73,10 @@ let cost_encoding =
(req "bytes_read" z)
(req "bytes_written" z))
let pp_cost ppf { allocations ; steps ; reads ; writes ; bytes_read ; bytes_written } =
Format.fprintf ppf
let pp_cost ppf {allocations; steps; reads; writes; bytes_read; bytes_written}
=
Format.fprintf
ppf
"(steps: %s, allocs: %s, reads: %s (%s bytes), writes: %s (%s bytes))"
(Z.to_string steps)
(Z.to_string allocations)
@ -83,20 +86,27 @@ let pp_cost ppf { allocations ; steps ; reads ; writes ; bytes_read ; bytes_writ
(Z.to_string bytes_written)
type error += Block_quota_exceeded (* `Temporary *)
type error += Operation_quota_exceeded (* `Temporary *)
let allocation_weight = Z.of_int 2
let step_weight = Z.of_int 1
let read_base_weight = Z.of_int 100
let write_base_weight = Z.of_int 160
let byte_read_weight = Z.of_int 10
let byte_written_weight = Z.of_int 15
let rescaling_bits = 7
let rescaling_mask =
Z.sub (Z.shift_left Z.one rescaling_bits) Z.one
let rescaling_mask = Z.sub (Z.shift_left Z.one rescaling_bits) Z.one
let scale (z : Z.t) = Z.shift_left z rescaling_bits
let rescale (z : Z.t) = Z.shift_right z rescaling_bits
let cost_to_internal_gas (cost : cost) : internal_gas =
@ -119,24 +129,20 @@ let internal_gas_to_gas internal_gas : Z.t * internal_gas =
let consume block_gas operation_gas internal_gas cost =
match operation_gas with
| Unaccounted -> ok (block_gas, Unaccounted, internal_gas)
| Unaccounted ->
ok (block_gas, Unaccounted, internal_gas)
| Limited {remaining} ->
let cost_internal_gas = cost_to_internal_gas cost in
let total_internal_gas =
Z.add cost_internal_gas internal_gas in
let gas, rest = internal_gas_to_gas total_internal_gas in
let total_internal_gas = Z.add cost_internal_gas internal_gas in
let (gas, rest) = internal_gas_to_gas total_internal_gas in
if Compare.Z.(gas > Z.zero) then
let remaining =
Z.sub remaining gas in
let block_remaining =
Z.sub block_gas gas in
if Compare.Z.(remaining < Z.zero)
then error Operation_quota_exceeded
else if Compare.Z.(block_remaining < Z.zero)
then error Block_quota_exceeded
let remaining = Z.sub remaining gas in
let block_remaining = Z.sub block_gas gas in
if Compare.Z.(remaining < Z.zero) then error Operation_quota_exceeded
else if Compare.Z.(block_remaining < Z.zero) then
error Block_quota_exceeded
else ok (block_remaining, Limited {remaining}, rest)
else
ok (block_gas, operation_gas, total_internal_gas)
else ok (block_gas, operation_gas, total_internal_gas)
let check_enough block_gas operation_gas internal_gas cost =
consume block_gas operation_gas internal_gas cost
@ -145,77 +151,90 @@ let check_enough block_gas operation_gas internal_gas cost =
let internal_gas_zero : internal_gas = Z.zero
let alloc_cost n =
{ allocations = scale (Z.of_int (n + 1)) ;
{
allocations = scale (Z.of_int (n + 1));
steps = Z.zero;
reads = Z.zero;
writes = Z.zero;
bytes_read = Z.zero;
bytes_written = Z.zero }
bytes_written = Z.zero;
}
let alloc_bytes_cost n =
alloc_cost ((n + 7) / 8)
let alloc_bytes_cost n = alloc_cost ((n + 7) / 8)
let alloc_bits_cost n =
alloc_cost ((n + 63) / 64)
let alloc_bits_cost n = alloc_cost ((n + 63) / 64)
let atomic_step_cost n =
{ allocations = Z.zero ;
{
allocations = Z.zero;
steps = Z.of_int (2 * n);
reads = Z.zero;
writes = Z.zero;
bytes_read = Z.zero;
bytes_written = Z.zero }
bytes_written = Z.zero;
}
let step_cost n =
{ allocations = Z.zero ;
{
allocations = Z.zero;
steps = scale (Z.of_int n);
reads = Z.zero;
writes = Z.zero;
bytes_read = Z.zero;
bytes_written = Z.zero }
bytes_written = Z.zero;
}
let free =
{ allocations = Z.zero ;
{
allocations = Z.zero;
steps = Z.zero;
reads = Z.zero;
writes = Z.zero;
bytes_read = Z.zero;
bytes_written = Z.zero }
bytes_written = Z.zero;
}
let read_bytes_cost n =
{ allocations = Z.zero ;
{
allocations = Z.zero;
steps = Z.zero;
reads = scale Z.one;
writes = Z.zero;
bytes_read = scale n;
bytes_written = Z.zero }
bytes_written = Z.zero;
}
let write_bytes_cost n =
{ allocations = Z.zero ;
{
allocations = Z.zero;
steps = Z.zero;
reads = Z.zero;
writes = Z.one;
bytes_read = Z.zero;
bytes_written = scale n }
bytes_written = scale n;
}
let ( +@ ) x y =
{ allocations = Z.add x.allocations y.allocations ;
{
allocations = Z.add x.allocations y.allocations;
steps = Z.add x.steps y.steps;
reads = Z.add x.reads y.reads;
writes = Z.add x.writes y.writes;
bytes_read = Z.add x.bytes_read y.bytes_read;
bytes_written = Z.add x.bytes_written y.bytes_written }
bytes_written = Z.add x.bytes_written y.bytes_written;
}
let ( *@ ) x y =
{ allocations = Z.mul (Z.of_int x) y.allocations ;
{
allocations = Z.mul (Z.of_int x) y.allocations;
steps = Z.mul (Z.of_int x) y.steps;
reads = Z.mul (Z.of_int x) y.reads;
writes = Z.mul (Z.of_int x) y.writes;
bytes_read = Z.mul (Z.of_int x) y.bytes_read;
bytes_written = Z.mul (Z.of_int x) y.bytes_written }
bytes_written = Z.mul (Z.of_int x) y.bytes_written;
}
let alloc_mbytes_cost n =
alloc_cost 12 +@ alloc_bytes_cost n
let alloc_mbytes_cost n = alloc_cost 12 +@ alloc_bytes_cost n
let () =
let open Data_encoding in
@ -224,8 +243,8 @@ let () =
~id:"gas_exhausted.operation"
~title:"Gas quota exceeded for the operation"
~description:
"A script or one of its callee took more \
time than the operation said it would"
"A script or one of its callee took more time than the operation said \
it would"
empty
(function Operation_quota_exceeded -> Some () | _ -> None)
(fun () -> Operation_quota_exceeded) ;
@ -234,8 +253,8 @@ let () =
~id:"gas_exhausted.block"
~title:"Gas quota exceeded for the block"
~description:
"The sum of gas consumed by all the operations in the block \
exceeds the hard gas limit per block"
"The sum of gas consumed by all the operations in the block exceeds the \
hard gas limit per block"
empty
(function Block_quota_exceeded -> Some () | _ -> None)
(fun () -> Block_quota_exceeded) ;
(fun () -> Block_quota_exceeded)

View File

@ -23,37 +23,49 @@
(* *)
(*****************************************************************************)
type t =
| Unaccounted
| Limited of { remaining : Z.t }
type t = Unaccounted | Limited of {remaining : Z.t}
type internal_gas
val encoding : t Data_encoding.encoding
val pp : Format.formatter -> t -> unit
type cost
val cost_encoding : cost Data_encoding.encoding
val pp_cost : Format.formatter -> cost -> unit
type error += Block_quota_exceeded (* `Temporary *)
type error += Operation_quota_exceeded (* `Temporary *)
val consume : Z.t -> t -> internal_gas -> cost -> (Z.t * t * internal_gas) tzresult
val consume :
Z.t -> t -> internal_gas -> cost -> (Z.t * t * internal_gas) tzresult
val check_enough : Z.t -> t -> internal_gas -> cost -> unit tzresult
val internal_gas_zero : internal_gas
val free : cost
val atomic_step_cost : int -> cost
val step_cost : int -> cost
val alloc_cost : int -> cost
val alloc_bytes_cost : int -> cost
val alloc_mbytes_cost : int -> cost
val alloc_bits_cost : int -> cost
val read_bytes_cost : Z.t -> cost
val write_bytes_cost : Z.t -> cost
val ( *@ ) : int -> cost -> cost
val ( +@ ) : cost -> cost -> cost

File diff suppressed because it is too large Load Diff

View File

@ -28,68 +28,98 @@ open Alpha_context
type error += Cannot_parse_operation (* `Branch *)
val current_level :
'a #RPC_context.simple ->
?offset:int32 -> 'a -> Level.t shell_tzresult Lwt.t
'a #RPC_context.simple -> ?offset:int32 -> 'a -> Level.t shell_tzresult Lwt.t
val levels_in_current_cycle :
'a #RPC_context.simple ->
?offset:int32 -> 'a -> (Raw_level.t * Raw_level.t) shell_tzresult Lwt.t
?offset:int32 ->
'a ->
(Raw_level.t * Raw_level.t) shell_tzresult Lwt.t
module Scripts : sig
val run_code :
'a #RPC_context.simple ->
'a -> Script.expr ->
(Script.expr * Script.expr * Tez.t * Chain_id.t * Contract.t option * Contract.t option * Z.t option * string) ->
(Script.expr *
packed_internal_operation list *
Contract.big_map_diff option) shell_tzresult Lwt.t
'a ->
Script.expr ->
Script.expr
* Script.expr
* Tez.t
* Chain_id.t
* Contract.t option
* Contract.t option
* Z.t option
* string ->
( Script.expr
* packed_internal_operation list
* Contract.big_map_diff option )
shell_tzresult
Lwt.t
val trace_code :
'a #RPC_context.simple ->
'a -> Script.expr ->
(Script.expr * Script.expr * Tez.t * Chain_id.t * Contract.t option * Contract.t option * Z.t option * string) ->
(Script.expr *
packed_internal_operation list *
Script_interpreter.execution_trace *
Contract.big_map_diff option) shell_tzresult Lwt.t
'a ->
Script.expr ->
Script.expr
* Script.expr
* Tez.t
* Chain_id.t
* Contract.t option
* Contract.t option
* Z.t option
* string ->
( Script.expr
* packed_internal_operation list
* Script_interpreter.execution_trace
* Contract.big_map_diff option )
shell_tzresult
Lwt.t
val typecheck_code :
'a #RPC_context.simple ->
'a -> (Script.expr * Z.t option) ->
'a ->
Script.expr * Z.t option ->
(Script_tc_errors.type_map * Gas.t) shell_tzresult Lwt.t
val typecheck_data :
'a #RPC_context.simple ->
'a -> Script.expr * Script.expr * Z.t option -> Gas.t shell_tzresult Lwt.t
'a ->
Script.expr * Script.expr * Z.t option ->
Gas.t shell_tzresult Lwt.t
val pack_data :
'a #RPC_context.simple ->
'a -> Script.expr * Script.expr * Z.t option -> (MBytes.t * Gas.t) shell_tzresult Lwt.t
'a ->
Script.expr * Script.expr * Z.t option ->
(MBytes.t * Gas.t) shell_tzresult Lwt.t
val run_operation :
'a #RPC_context.simple ->
'a -> packed_operation * Chain_id.t ->
(packed_protocol_data * Apply_results.packed_operation_metadata) shell_tzresult Lwt.t
'a ->
packed_operation * Chain_id.t ->
(packed_protocol_data * Apply_results.packed_operation_metadata)
shell_tzresult
Lwt.t
val entrypoint_type :
'a #RPC_context.simple ->
'a -> Script.expr * string -> Script.expr shell_tzresult Lwt.t
'a ->
Script.expr * string ->
Script.expr shell_tzresult Lwt.t
val list_entrypoints :
'a #RPC_context.simple ->
'a -> Script.expr ->
(Michelson_v1_primitives.prim list list *
(string * Script.expr) list) shell_tzresult Lwt.t
'a ->
Script.expr ->
(Michelson_v1_primitives.prim list list * (string * Script.expr) list)
shell_tzresult
Lwt.t
end
module Forge : sig
module Manager : sig
val operations :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
branch:Block_hash.t ->
source:public_key_hash ->
?sourcePubKey:public_key ->
@ -97,19 +127,23 @@ module Forge : sig
fee:Tez.t ->
gas_limit:Z.t ->
storage_limit:Z.t ->
packed_manager_operation list -> MBytes.t shell_tzresult Lwt.t
packed_manager_operation list ->
MBytes.t shell_tzresult Lwt.t
val reveal :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
branch:Block_hash.t ->
source:public_key_hash ->
sourcePubKey:public_key ->
counter:counter ->
fee:Tez.t ->
unit -> MBytes.t shell_tzresult Lwt.t
unit ->
MBytes.t shell_tzresult Lwt.t
val transaction :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
branch:Block_hash.t ->
source:public_key_hash ->
?sourcePubKey:public_key ->
@ -121,10 +155,12 @@ module Forge : sig
gas_limit:Z.t ->
storage_limit:Z.t ->
fee:Tez.t ->
unit -> MBytes.t shell_tzresult Lwt.t
unit ->
MBytes.t shell_tzresult Lwt.t
val origination :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
branch:Block_hash.t ->
source:public_key_hash ->
?sourcePubKey:public_key ->
@ -135,10 +171,12 @@ module Forge : sig
gas_limit:Z.t ->
storage_limit:Z.t ->
fee:Tez.t ->
unit -> MBytes.t shell_tzresult Lwt.t
unit ->
MBytes.t shell_tzresult Lwt.t
val delegation :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
branch:Block_hash.t ->
source:public_key_hash ->
?sourcePubKey:public_key ->
@ -146,74 +184,88 @@ module Forge : sig
fee:Tez.t ->
public_key_hash option ->
MBytes.t shell_tzresult Lwt.t
end
val endorsement :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
branch:Block_hash.t ->
level:Raw_level.t ->
unit -> MBytes.t shell_tzresult Lwt.t
unit ->
MBytes.t shell_tzresult Lwt.t
val proposals :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
branch:Block_hash.t ->
source:public_key_hash ->
period:Voting_period.t ->
proposals:Protocol_hash.t list ->
unit -> MBytes.t shell_tzresult Lwt.t
unit ->
MBytes.t shell_tzresult Lwt.t
val ballot :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
branch:Block_hash.t ->
source:public_key_hash ->
period:Voting_period.t ->
proposal:Protocol_hash.t ->
ballot:Vote.ballot ->
unit -> MBytes.t shell_tzresult Lwt.t
unit ->
MBytes.t shell_tzresult Lwt.t
val seed_nonce_revelation :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
branch:Block_hash.t ->
level:Raw_level.t ->
nonce:Nonce.t ->
unit -> MBytes.t shell_tzresult Lwt.t
unit ->
MBytes.t shell_tzresult Lwt.t
val double_baking_evidence :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
branch:Block_hash.t ->
bh1:Block_header.t ->
bh2:Block_header.t ->
unit -> MBytes.t shell_tzresult Lwt.t
unit ->
MBytes.t shell_tzresult Lwt.t
val double_endorsement_evidence :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
branch:Block_hash.t ->
op1:Kind.endorsement operation ->
op2:Kind.endorsement operation ->
unit -> MBytes.t shell_tzresult Lwt.t
unit ->
MBytes.t shell_tzresult Lwt.t
val protocol_data :
'a #RPC_context.simple -> 'a ->
'a #RPC_context.simple ->
'a ->
priority:int ->
?seed_nonce_hash:Nonce_hash.t ->
?proof_of_work_nonce:MBytes.t ->
unit -> MBytes.t shell_tzresult Lwt.t
unit ->
MBytes.t shell_tzresult Lwt.t
end
module Parse : sig
val operations :
'a #RPC_context.simple -> 'a ->
?check:bool -> Operation.raw list ->
'a #RPC_context.simple ->
'a ->
?check:bool ->
Operation.raw list ->
Operation.packed list shell_tzresult Lwt.t
val block :
'a #RPC_context.simple -> 'a ->
Block_header.shell_header -> MBytes.t ->
'a #RPC_context.simple ->
'a ->
Block_header.shell_header ->
MBytes.t ->
Block_header.protocol_data shell_tzresult Lwt.t
end
val register : unit -> unit

View File

@ -2,7 +2,6 @@
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* Copyright (c) 2019 Nomadic Labs <contact@nomadic-labs.com> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
@ -24,355 +23,36 @@
(* *)
(*****************************************************************************)
(* Delegated storage changed type of value from Contract_hash to
Contract_repr. Move all 'delegated' data into a storage with
the original type, then copy over into the new storage. *)
let migrate_delegated ctxt contract =
let path = "contracts" :: (* module Contract *)
"index" :: (* module Indexed_context *)
Contract_repr.Index.to_path contract [
"delegated" ; (* module Delegated *)
] in
let path_tmp = "contracts" :: (* module Contract *)
"index" :: (* module Indexed_context *)
Contract_repr.Index.to_path contract [
"delegated_004" ; (* module Delegated *)
] in
Raw_context.dir_mem ctxt path >>= fun exists ->
if exists then
Raw_context.copy ctxt path path_tmp >>=? fun ctxt ->
Raw_context.remove_rec ctxt path >>= fun ctxt ->
Storage.Contract.Delegated_004.fold (ctxt, contract) ~init:(Ok ctxt) ~f:(fun delegated ctxt ->
Lwt.return ctxt >>=? fun ctxt ->
let originated = Contract_repr.originated_contract_004 delegated in
Storage.Contract.Delegated.add (ctxt, contract) originated >>= fun ctxt ->
return ctxt
) >>=? fun ctxt ->
Raw_context.remove_rec ctxt path_tmp >>= fun ctxt ->
return ctxt
else
return ctxt
let transform_script:
(manager_pkh: Signature.Public_key_hash.t ->
script_code: Script_repr.lazy_expr ->
script_storage: Script_repr.lazy_expr ->
(Script_repr.lazy_expr * Script_repr.lazy_expr) tzresult Lwt.t) ->
manager_pkh: Signature.Public_key_hash.t ->
Raw_context.t ->
Contract_repr.t ->
Script_repr.lazy_expr ->
Raw_context.t tzresult Lwt.t =
fun transformation ~manager_pkh ctxt contract code ->
Storage.Contract.Storage.get ctxt contract >>=? fun (_ctxt, storage) ->
transformation manager_pkh code storage >>=? fun (migrated_code, migrated_storage) ->
(* Set the migrated script code for free *)
Storage.Contract.Code.set_free ctxt contract migrated_code >>=? fun (ctxt, code_size_diff) ->
(* Set the migrated script storage for free *)
Storage.Contract.Storage.set_free ctxt contract migrated_storage >>=? fun (ctxt, storage_size_diff) ->
Storage.Contract.Used_storage_space.get ctxt contract >>=? fun used_space ->
let total_size = Z.(add (of_int code_size_diff) (add (of_int storage_size_diff) used_space)) in
(* Free storage space for migrated contracts *)
Storage.Contract.Used_storage_space.set ctxt contract total_size >>=? fun ctxt ->
Storage.Contract.Paid_storage_space.get ctxt contract >>=? fun paid_space ->
if Compare.Z.(paid_space < total_size) then
Storage.Contract.Paid_storage_space.set ctxt contract total_size >>=? fun ctxt ->
return ctxt
else
return ctxt
let manager_script_storage: Signature.Public_key_hash.t -> Script_repr.lazy_expr =
fun manager_pkh ->
let open Micheline in
Script_repr.lazy_expr @@ strip_locations @@
(* store in optimized binary representation - as unparsed with [Optimized]. *)
let bytes = Data_encoding.Binary.to_bytes_exn Signature.Public_key_hash.encoding manager_pkh in
Bytes (0, bytes)
(* If the given contract is not allocated, we'll allocate it with 1 mutez,
so that the migrated contracts' managers don't have to pay origination burn *)
let allocate_contract ctxt contract =
Contract_storage.allocated ctxt contract >>=? function
| true ->
return ctxt
| false ->
Contract_storage.credit ctxt contract Tez_repr.one_mutez
(* Process an individual contract *)
let process_contract_add_manager contract ctxt =
let open Legacy_script_support_repr in
match Contract_repr.is_originated contract with
| None -> return ctxt (* Only process originated contracts *)
| Some _ -> begin
Storage.Contract.Counter.remove ctxt contract >>= fun ctxt ->
Storage.Contract.Spendable_004.mem ctxt contract >>= fun is_spendable ->
Storage.Contract.Delegatable_004.mem ctxt contract >>= fun is_delegatable ->
Storage.Contract.Spendable_004.del ctxt contract >>= fun ctxt ->
Storage.Contract.Delegatable_004.del ctxt contract >>= fun ctxt ->
(* Try to get script code (ignore ctxt update to discard the initialization) *)
Storage.Contract.Code.get_option ctxt contract >>=? fun (_ctxt, code) ->
(* Get the manager of the originated contract *)
Contract_storage.get_manager_004 ctxt contract >>=? fun manager_pkh ->
let manager = Contract_repr.implicit_contract manager_pkh in
Storage.Contract.Manager.remove ctxt contract >>= fun ctxt ->
match code with
| Some code ->
(*
| spendable | delegatable | template |
|-----------+-------------+------------------|
| true | true | add_do |
| true | false | add_do |
| false | true | add_set_delegate |
| false | false | nothing |
*)
if is_spendable then
transform_script add_do ~manager_pkh ctxt contract code >>=? fun ctxt ->
allocate_contract ctxt manager
else if is_delegatable then
transform_script add_set_delegate ~manager_pkh ctxt contract code >>=? fun ctxt ->
allocate_contract ctxt manager
else if has_default_entrypoint code then
transform_script
(fun ~manager_pkh:_ ~script_code ~script_storage ->
add_root_entrypoint script_code >>=? fun script_code ->
return (script_code, script_storage))
~manager_pkh ctxt contract code
else
return ctxt
| None -> begin
(* Initialize the script code for free *)
Storage.Contract.Code.init_free ctxt contract manager_script_code >>=? fun (ctxt, code_size) ->
let storage = manager_script_storage manager_pkh in
(* Initialize the script storage for free *)
Storage.Contract.Storage.init_free ctxt contract storage >>=? fun (ctxt, storage_size) ->
let total_size = Z.(add (of_int code_size) (of_int storage_size)) in
(* Free storage space for migrated contracts *)
Storage.Contract.Paid_storage_space.init_set ctxt contract total_size >>= fun ctxt ->
Storage.Contract.Used_storage_space.init_set ctxt contract total_size >>= fun ctxt ->
allocate_contract ctxt manager
end
end
(* The [[update_contract_script]] function returns a copy of its
argument (the Micheline AST of a contract script) with "ADDRESS"
replaced by "ADDRESS; CHAIN_ID; PAIR".
[[Micheline.strip_locations]] should be called on the resulting
Micheline AST to get meaningful locations. *)
let rec update_contract_script : ('l, 'p) Micheline.node -> ('l, 'p) Micheline.node
= function
| Micheline.Seq (_,
Micheline.Prim (_, Michelson_v1_primitives.I_ADDRESS, [], []) ::
l) ->
Micheline.Seq (0,
Micheline.Prim (0, Michelson_v1_primitives.I_ADDRESS, [], []) ::
Micheline.Prim (0, Michelson_v1_primitives.I_CHAIN_ID, [], []) ::
Micheline.Prim (0, Michelson_v1_primitives.I_PAIR, [], []) :: l)
| Micheline.Seq (_, a :: l) ->
let a' = update_contract_script a in
let b = Micheline.Seq (0, l) in
let b' = update_contract_script b in
begin match b' with
| Micheline.Seq (_, l') ->
Micheline.Seq (0, a' :: l')
| _ -> assert false
end
| Micheline.Prim (_, p, l, annot) ->
Micheline.Prim (0, p, List.map update_contract_script l, annot)
| script -> script
let migrate_multisig_script (ctxt : Raw_context.t) (contract : Contract_repr.t)
(code : Script_repr.expr) : Raw_context.t tzresult Lwt.t =
let migrated_code =
Script_repr.lazy_expr @@ Micheline.strip_locations @@
update_contract_script @@ Micheline.root code
in
Storage.Contract.Code.set_free ctxt contract migrated_code >>=? fun (ctxt, _code_size_diff) ->
(* Set the spendable and delegatable flags to false so that no entrypoint gets added by
the [[process_contract_add_manager]] function. *)
Storage.Contract.Spendable_004.set ctxt contract false >>= fun ctxt ->
Storage.Contract.Delegatable_004.set ctxt contract false >>= fun ctxt ->
return ctxt
(* The hash of the multisig contract; only contracts with this exact
hash are going to be updated by the [[update_contract_script]]
function. *)
let multisig_hash : Script_expr_hash.t =
Script_expr_hash.of_bytes_exn @@
MBytes.of_hex @@
`Hex "475e37a6386d0b85890eb446db1faad67f85fc814724ad07473cac8c0a124b31"
let process_contract_multisig (contract : Contract_repr.t) (ctxt : Raw_context.t) =
Contract_storage.get_script ctxt contract >>=? fun (ctxt, script_opt) ->
match script_opt with
| None ->
(* Do nothing on scriptless contracts *)
return ctxt
| Some { Script_repr.code = code ; Script_repr.storage = _storage } ->
(* The contract has some script, only try to modify it if it has
the hash of the multisig contract *)
Lwt.return (Script_repr.force_decode code) >>=? fun (code, _gas_cost) ->
let bytes =
Data_encoding.Binary.to_bytes_exn Script_repr.expr_encoding code
in
let hash = Script_expr_hash.hash_bytes [ bytes ] in
if Script_expr_hash.(hash = multisig_hash) then
migrate_multisig_script ctxt contract code
else
return ctxt
(* Process an individual contract *)
let process_contract contract ctxt =
process_contract_multisig contract ctxt >>=? fun ctxt ->
process_contract_add_manager contract ctxt >>=? fun ctxt ->
return ctxt
let invoice_contract ctxt kt1_addr amount =
let amount = Tez_repr.of_mutez_exn (Int64.(mul 1_000_000L (of_int amount))) in
match Contract_repr.of_b58check kt1_addr with
| Ok recipient -> begin
Contract_storage.credit ctxt recipient amount >>= function
| Ok ctxt -> return ctxt
| Error _ -> return ctxt end
| Error _ -> return ctxt
(* Extract Big_maps from their parent contract directory,
recompute their used space, and assign them an ID. *)
let migrate_contract_big_map ctxt contract =
Storage.Contract.Code.get_option ctxt contract >>=? function
| ctxt, None -> return ctxt
| ctxt, Some code ->
Storage.Contract.Storage.get ctxt contract >>=? fun (ctxt, storage) ->
let extract_big_map_types expr =
let open Michelson_v1_primitives in
let open Micheline in
match Micheline.root expr with
| Seq (_, [ Prim (_, K_storage, [ expr ], _) ; _ ; _ ])
| Seq (_, [ _ ; Prim (_, K_storage, [ expr ], _) ; _ ])
| Seq (_, [ _ ; _ ; Prim (_, K_storage, [ expr ], _) ]) ->
begin match expr with
| Prim (_, T_pair, [ Prim (_, T_big_map, [ kt ; vt ], _ ) ; _ ], _) -> Some (kt, vt)
| _ -> None
end
| _ -> None in
let rewrite_big_map expr id =
let open Michelson_v1_primitives in
let open Micheline in
match Micheline.root expr with
| Prim (_, D_Pair, [ Seq (_, _ (* ignore_unused_origination_literal *)) ; pannot ], sannot) ->
Micheline.strip_locations (Prim (0, D_Pair, [ Int (0, id) ; pannot ], sannot))
| _ -> assert false in
Lwt.return (Script_repr.force_decode code) >>=? fun (code, _) ->
match extract_big_map_types code with
| None -> return ctxt
| Some (kt, vt) ->
Lwt.return (Script_repr.force_decode storage) >>=? fun (storage, _) ->
Storage.Big_map.Next.incr ctxt >>=? fun (ctxt, id) ->
let contract_path suffix =
"contracts" :: (* module Contract *)
"index" :: (* module Indexed_context *)
Contract_repr.Index.to_path contract suffix in
let old_path = contract_path [ "big_map" ] in
let storage = rewrite_big_map storage id in
Storage.Contract.Storage.set ctxt contract (Script_repr.lazy_expr storage) >>=? fun (ctxt, _) ->
let kt = Micheline.strip_locations (Script_repr.strip_annotations kt) in
let vt = Micheline.strip_locations (Script_repr.strip_annotations vt) in
Storage.Big_map.Key_type.init ctxt id kt >>=? fun ctxt ->
Storage.Big_map.Value_type.init ctxt id vt >>=? fun ctxt ->
Raw_context.dir_mem ctxt old_path >>= fun exists ->
if exists then
let read_size ctxt key =
Raw_context.get ctxt key >>=? fun len ->
match Data_encoding.(Binary.of_bytes int31) len with
| None -> assert false
| Some len -> return len in
let iter_sizes f (ctxt, acc) =
let rec dig i path (ctxt, acc) =
if Compare.Int.(i <= 0) then
Raw_context.fold ctxt path ~init:(ok (ctxt, acc)) ~f:begin fun k acc ->
Lwt.return acc >>=? fun (ctxt, acc) ->
match k with
| `Dir _ -> return (ctxt, acc)
| `Key file ->
match List.rev file with
| last :: _ when Compare.String.(last = "data") ->
return (ctxt, acc)
| last :: _ when Compare.String.(last = "len") ->
read_size ctxt file >>=? fun len ->
return (ctxt, f len acc)
| _ -> assert false
end
else
Raw_context.fold ctxt path ~init:(ok (ctxt, acc)) ~f:begin fun k acc ->
Lwt.return acc >>=? fun (ctxt, acc) ->
match k with
| `Dir k -> dig (i-1) k (ctxt, acc)
| `Key _ -> return (ctxt, acc)
end in
dig Script_expr_hash.path_length old_path (ctxt, acc) in
iter_sizes
(fun s acc -> (acc |> Z.add (Z.of_int s) |> Z.add (Z.of_int 65)))
(ctxt, (Z.of_int 0)) >>=? fun (ctxt, total_bytes) ->
Storage.Big_map.Total_bytes.init ctxt id total_bytes >>=? fun ctxt ->
let new_path = "big_maps" :: (* module Big_map *)
"index" :: (* module Indexed_context *)
Storage.Big_map.Index.to_path id [
"contents" ; (* module Delegated *)
] in
Raw_context.copy ctxt old_path new_path >>=? fun ctxt ->
Raw_context.remove_rec ctxt old_path >>= fun ctxt ->
read_size ctxt (contract_path [ "len" ; "code" ]) >>=? fun code_size ->
read_size ctxt (contract_path [ "len" ; "storage" ]) >>=? fun storage_size ->
let total_bytes =
total_bytes |>
Z.add (Z.of_int 33) |>
Z.add (Z.of_int code_size) |>
Z.add (Z.of_int storage_size) in
Storage.Contract.Used_storage_space.get ctxt contract >>=? fun previous_size ->
Storage.Contract.Paid_storage_space.get ctxt contract >>=? fun paid_bytes ->
let change = Z.sub paid_bytes previous_size in
Storage.Contract.Used_storage_space.set ctxt contract total_bytes >>=? fun ctxt ->
Storage.Contract.Paid_storage_space.set ctxt contract (Z.add total_bytes change)
else
Storage.Big_map.Total_bytes.init ctxt id Z.zero >>=? fun ctxt ->
return ctxt
(* This is the genesis protocol: initialise the state *)
let prepare_first_block ctxt ~typecheck ~level ~timestamp ~fitness =
Raw_context.prepare_first_block
~level ~timestamp ~fitness ctxt >>=? fun (previous_protocol, ctxt) ->
Storage.Big_map.Next.init ctxt >>=? fun ctxt ->
Raw_context.prepare_first_block ~level ~timestamp ~fitness ctxt
>>=? fun (previous_protocol, ctxt) ->
match previous_protocol with
| Genesis param ->
Commitment_storage.init ctxt param.commitments >>=? fun ctxt ->
Roll_storage.init ctxt >>=? fun ctxt ->
Seed_storage.init ctxt >>=? fun ctxt ->
Contract_storage.init ctxt >>=? fun ctxt ->
Bootstrap_storage.init ctxt
Commitment_storage.init ctxt param.commitments
>>=? fun ctxt ->
Roll_storage.init ctxt
>>=? fun ctxt ->
Seed_storage.init ctxt
>>=? fun ctxt ->
Contract_storage.init ctxt
>>=? fun ctxt ->
Bootstrap_storage.init
ctxt
~typecheck
?ramp_up_cycles:param.security_deposit_ramp_up_cycles
?no_reward_cycles:param.no_reward_cycles
param.bootstrap_accounts
param.bootstrap_contracts >>=? fun ctxt ->
Roll_storage.init_first_cycles ctxt >>=? fun ctxt ->
Vote_storage.init ctxt >>=? fun ctxt ->
Storage.Block_priority.init ctxt 0 >>=? fun ctxt ->
Vote_storage.freeze_listings ctxt >>=? fun ctxt ->
return ctxt
| Athens_004 ->
Storage.Vote.Current_quorum_004.get ctxt >>=? fun quorum ->
Storage.Vote.Participation_ema.init ctxt quorum >>=? fun ctxt ->
Storage.Vote.Current_quorum_004.delete ctxt >>=? fun ctxt ->
Storage.Block_priority.init ctxt 0 >>=? fun ctxt ->
Storage.Last_block_priority.delete ctxt >>=? fun ctxt ->
Storage.Contract.fold ctxt ~init:(Ok ctxt)
~f:(fun contract ctxt ->
Lwt.return ctxt >>=? fun ctxt ->
migrate_delegated ctxt contract >>=? fun ctxt ->
migrate_contract_big_map ctxt contract >>=? fun ctxt ->
process_contract contract ctxt)
param.bootstrap_contracts
>>=? fun ctxt ->
invoice_contract ctxt "KT1DUfaMfTRZZkvZAYQT5b3byXnvqoAykc43" 500 >>=? fun ctxt ->
Roll_storage.init_first_cycles ctxt
>>=? fun ctxt ->
Vote_storage.init ctxt
>>=? fun ctxt ->
Storage.Block_priority.init ctxt 0
>>=? fun ctxt ->
Vote_storage.freeze_listings ctxt >>=? fun ctxt -> return ctxt
| Babylon_005 ->
return ctxt
let prepare ctxt ~level ~predecessor_timestamp ~timestamp ~fitness =

File diff suppressed because it is too large Load Diff

View File

@ -60,10 +60,8 @@ val add_set_delegate:
(** Checks if a contract was declaring a default entrypoint somewhere
else than at the root, in which case its type changes when
entrypoints are activated. *)
val has_default_entrypoint:
Script_repr.lazy_expr -> bool
val has_default_entrypoint : Script_repr.lazy_expr -> bool
(** Adds a [%root] annotation on the toplevel parameter construct. *)
val add_root_entrypoint :
script_code: Script_repr.lazy_expr ->
Script_repr.lazy_expr tzresult Lwt.t
script_code:Script_repr.lazy_expr -> Script_repr.lazy_expr tzresult Lwt.t

View File

@ -35,6 +35,7 @@ type t = {
include Compare.Make (struct
type nonrec t = t
let compare {level = l1} {level = l2} = Raw_level_repr.compare l1 l2
end)
@ -43,74 +44,102 @@ type level = t
let pp ppf {level} = Raw_level_repr.pp ppf level
let pp_full ppf l =
Format.fprintf ppf
Format.fprintf
ppf
"%a.%ld (cycle %a.%ld) (vote %a.%ld)"
Raw_level_repr.pp l.level l.level_position
Cycle_repr.pp l.cycle l.cycle_position
Voting_period_repr.pp l.voting_period l.voting_period_position
Raw_level_repr.pp
l.level
l.level_position
Cycle_repr.pp
l.cycle
l.cycle_position
Voting_period_repr.pp
l.voting_period
l.voting_period_position
let encoding =
let open Data_encoding in
conv
(fun { level ; level_position ;
cycle ; cycle_position ;
voting_period; voting_period_position ;
(fun { level;
level_position;
cycle;
cycle_position;
voting_period;
voting_period_position;
expected_commitment } ->
(level, level_position,
cycle, cycle_position,
voting_period, voting_period_position,
( level,
level_position,
cycle,
cycle_position,
voting_period,
voting_period_position,
expected_commitment ))
(fun (level, level_position,
cycle, cycle_position,
voting_period, voting_period_position,
(fun ( level,
level_position,
cycle,
cycle_position,
voting_period,
voting_period_position,
expected_commitment ) ->
{ level ; level_position ;
cycle ; cycle_position ;
voting_period ; voting_period_position ;
expected_commitment })
{
level;
level_position;
cycle;
cycle_position;
voting_period;
voting_period_position;
expected_commitment;
})
(obj7
(req "level"
(req
"level"
~description:
"The level of the block relative to genesis. This is also \
the Shell's notion of level"
"The level of the block relative to genesis. This is also the \
Shell's notion of level"
Raw_level_repr.encoding)
(req "level_position"
(req
"level_position"
~description:
"The level of the block relative to the block that starts \
protocol alpha. This is specific to the protocol \
alpha. Other protocols might or might not include a \
similar notion."
protocol alpha. This is specific to the protocol alpha. Other \
protocols might or might not include a similar notion."
int32)
(req "cycle"
(req
"cycle"
~description:
"The current cycle's number. Note that cycles are a \
protocol-specific notion. As a result, the cycle number starts at 0 \
with the first block of protocol alpha."
protocol-specific notion. As a result, the cycle number starts \
at 0 with the first block of protocol alpha."
Cycle_repr.encoding)
(req "cycle_position"
(req
"cycle_position"
~description:
"The current level of the block relative to the first \
block of the current cycle."
"The current level of the block relative to the first block of \
the current cycle."
int32)
(req "voting_period"
(req
"voting_period"
~description:
"The current voting period's index. Note that cycles are a \
protocol-specific notion. As a result, the voting period \
index starts at 0 with the first block of protocol alpha."
protocol-specific notion. As a result, the voting period index \
starts at 0 with the first block of protocol alpha."
Voting_period_repr.encoding)
(req "voting_period_position"
(req
"voting_period_position"
~description:
"The current level of the block relative to the first \
block of the current voting period."
"The current level of the block relative to the first block of \
the current voting period."
int32)
(req "expected_commitment"
(req
"expected_commitment"
~description:
"Tells wether the baker of this block has to commit a seed \
nonce hash."
"Tells wether the baker of this block has to commit a seed nonce \
hash."
bool))
let root first_level =
{ level = first_level ;
{
level = first_level;
level_position = 0l;
cycle = Cycle_repr.root;
cycle_position = 0l;
@ -119,30 +148,38 @@ let root first_level =
expected_commitment = false;
}
let from_raw
~first_level ~blocks_per_cycle ~blocks_per_voting_period
~blocks_per_commitment
level =
let from_raw ~first_level ~blocks_per_cycle ~blocks_per_voting_period
~blocks_per_commitment level =
let raw_level = Raw_level_repr.to_int32 level in
let first_level = Raw_level_repr.to_int32 first_level in
let level_position =
Compare.Int32.max 0l (Int32.sub raw_level first_level) in
Compare.Int32.max 0l (Int32.sub raw_level first_level)
in
let cycle =
Cycle_repr.of_int32_exn (Int32.div level_position blocks_per_cycle) in
Cycle_repr.of_int32_exn (Int32.div level_position blocks_per_cycle)
in
let cycle_position = Int32.rem level_position blocks_per_cycle in
let voting_period =
Voting_period_repr.of_int32_exn
(Int32.div level_position blocks_per_voting_period) in
(Int32.div level_position blocks_per_voting_period)
in
let voting_period_position =
Int32.rem level_position blocks_per_voting_period in
Int32.rem level_position blocks_per_voting_period
in
let expected_commitment =
Compare.Int32.(Int32.rem cycle_position blocks_per_commitment =
Int32.pred blocks_per_commitment) in
{ level ; level_position ;
cycle ; cycle_position ;
voting_period ; voting_period_position ;
expected_commitment }
Compare.Int32.(
Int32.rem cycle_position blocks_per_commitment
= Int32.pred blocks_per_commitment)
in
{
level;
level_position;
cycle;
cycle_position;
voting_period;
voting_period_position;
expected_commitment;
}
let diff {level = l1; _} {level = l2; _} =
Int32.sub (Raw_level_repr.to_int32 l1) (Raw_level_repr.to_int32 l2)

View File

@ -24,18 +24,22 @@
(*****************************************************************************)
type t = private {
level: Raw_level_repr.t (** The level of the block relative to genesis. This
is also the Shell's notion of level. *);
level_position: int32 (** The level of the block relative to the block that
level : Raw_level_repr.t;
(** The level of the block relative to genesis. This
is also the Shell's notion of level. *)
level_position : int32;
(** The level of the block relative to the block that
starts protocol alpha. This is specific to the
protocol alpha. Other protocols might or might not
include a similar notion. *);
cycle: Cycle_repr.t (** The current cycle's number. Note that cycles are a
include a similar notion. *)
cycle : Cycle_repr.t;
(** The current cycle's number. Note that cycles are a
protocol-specific notion. As a result, the cycle
number starts at 0 with the first block of protocol
alpha. *);
cycle_position: int32 (** The current level of the block relative to the first
block of the current cycle. *);
alpha. *)
cycle_position : int32;
(** The current level of the block relative to the first
block of the current cycle. *)
voting_period : Voting_period_repr.t;
voting_period_position : int32;
expected_commitment : bool;
@ -47,14 +51,14 @@ type t = private {
level_position = cycle * blocks_per_cycle + cycle_position
*)
type level = t
include Compare.S with type t := level
val encoding : level Data_encoding.t
val pp : Format.formatter -> level -> unit
val pp_full : Format.formatter -> level -> unit
val root : Raw_level_repr.t -> level
@ -64,6 +68,7 @@ val from_raw:
blocks_per_cycle:int32 ->
blocks_per_voting_period:int32 ->
blocks_per_commitment:int32 ->
Raw_level_repr.t -> level
Raw_level_repr.t ->
level
val diff : level -> level -> int32

View File

@ -28,8 +28,11 @@ open Level_repr
let from_raw c ?offset l =
let l =
match offset with
| None -> l
| Some o -> Raw_level_repr.(of_int32_exn (Int32.add (to_int32 l) o)) in
| None ->
l
| Some o ->
Raw_level_repr.(of_int32_exn (Int32.add (to_int32 l) o))
in
let constants = Raw_context.constants c in
let first_level = Raw_context.first_level c in
Level_repr.from_raw
@ -39,27 +42,32 @@ let from_raw c ?offset l =
~blocks_per_commitment:constants.Constants_repr.blocks_per_commitment
l
let root c =
Level_repr.root (Raw_context.first_level c)
let root c = Level_repr.root (Raw_context.first_level c)
let succ c l = from_raw c (Raw_level_repr.succ l.level)
let pred c l =
match Raw_level_repr.pred l.Level_repr.level with
| None -> None
| Some l -> Some (from_raw c l)
| None ->
None
| Some l ->
Some (from_raw c l)
let current ctxt = Raw_context.current_level ctxt
let previous ctxt =
let l = current ctxt in
match pred ctxt l with
| None -> assert false (* We never validate the Genesis... *)
| Some p -> p
| None ->
assert false (* We never validate the Genesis... *)
| Some p ->
p
let first_level_in_cycle ctxt c =
let constants = Raw_context.constants ctxt in
let first_level = Raw_context.first_level ctxt in
from_raw ctxt
from_raw
ctxt
(Raw_level_repr.of_int32_exn
(Int32.add
(Raw_level_repr.to_int32 first_level)
@ -69,14 +77,15 @@ let first_level_in_cycle ctxt c =
let last_level_in_cycle ctxt c =
match pred ctxt (first_level_in_cycle ctxt (Cycle_repr.succ c)) with
| None -> assert false
| Some x -> x
| None ->
assert false
| Some x ->
x
let levels_in_cycle ctxt cycle =
let first = first_level_in_cycle ctxt cycle in
let rec loop n acc =
if Cycle_repr.(n.cycle = first.cycle)
then loop (succ ctxt n) (n :: acc)
if Cycle_repr.(n.cycle = first.cycle) then loop (succ ctxt n) (n :: acc)
else acc
in
loop first []
@ -84,8 +93,7 @@ let levels_in_cycle ctxt cycle =
let levels_in_current_cycle ctxt ?(offset = 0l) () =
let current_cycle = Cycle_repr.to_int32 (current ctxt).cycle in
let cycle = Int32.add current_cycle offset in
if Compare.Int32.(cycle < 0l) then
[]
if Compare.Int32.(cycle < 0l) then []
else
let cycle = Cycle_repr.of_int32_exn cycle in
levels_in_cycle ctxt cycle
@ -93,20 +101,18 @@ let levels_in_current_cycle ctxt ?(offset = 0l) () =
let levels_with_commitments_in_cycle ctxt c =
let first = first_level_in_cycle ctxt c in
let rec loop n acc =
if Cycle_repr.(n.cycle = first.cycle)
then
if n.expected_commitment then
loop (succ ctxt n) (n :: acc)
else
loop (succ ctxt n) acc
if Cycle_repr.(n.cycle = first.cycle) then
if n.expected_commitment then loop (succ ctxt n) (n :: acc)
else loop (succ ctxt n) acc
else acc
in
loop first []
let last_allowed_fork_level c =
let level = Raw_context.current_level c in
let preserved_cycles = Constants_storage.preserved_cycles c in
match Cycle_repr.sub level.cycle preserved_cycles with
| None -> Raw_level_repr.root
| Some cycle -> (first_level_in_cycle c cycle).level
| None ->
Raw_level_repr.root
| Some cycle ->
(first_level_in_cycle c cycle).level

View File

@ -24,17 +24,24 @@
(*****************************************************************************)
val current : Raw_context.t -> Level_repr.t
val previous : Raw_context.t -> Level_repr.t
val root : Raw_context.t -> Level_repr.t
val from_raw: Raw_context.t -> ?offset:int32 -> Raw_level_repr.t -> Level_repr.t
val from_raw :
Raw_context.t -> ?offset:int32 -> Raw_level_repr.t -> Level_repr.t
val pred : Raw_context.t -> Level_repr.t -> Level_repr.t option
val succ : Raw_context.t -> Level_repr.t -> Level_repr.t
val first_level_in_cycle : Raw_context.t -> Cycle_repr.t -> Level_repr.t
val last_level_in_cycle : Raw_context.t -> Cycle_repr.t -> Level_repr.t
val levels_in_cycle : Raw_context.t -> Cycle_repr.t -> Level_repr.t list
val levels_in_current_cycle :
Raw_context.t -> ?offset:int32 -> unit -> Level_repr.t list

View File

@ -26,25 +26,33 @@
(* Tezos Protocol Implementation - Protocol Signature Instance *)
type block_header_data = Alpha_context.Block_header.protocol_data
type block_header = Alpha_context.Block_header.t = {
shell : Block_header.shell_header;
protocol_data : block_header_data;
}
let block_header_data_encoding = Alpha_context.Block_header.protocol_data_encoding
let block_header_data_encoding =
Alpha_context.Block_header.protocol_data_encoding
type block_header_metadata = Apply_results.block_metadata
let block_header_metadata_encoding = Apply_results.block_metadata_encoding
type operation_data = Alpha_context.packed_protocol_data =
| Operation_data : 'kind Alpha_context.Operation.protocol_data -> operation_data
| Operation_data :
'kind Alpha_context.Operation.protocol_data
-> operation_data
let operation_data_encoding = Alpha_context.Operation.protocol_data_encoding
type operation_receipt = Apply_results.packed_operation_metadata =
| Operation_metadata : 'kind Apply_results.operation_metadata -> operation_receipt
| Operation_metadata :
'kind Apply_results.operation_metadata
-> operation_receipt
| No_operation_metadata : operation_receipt
let operation_receipt_encoding =
Apply_results.operation_metadata_encoding
let operation_receipt_encoding = Apply_results.operation_metadata_encoding
let operation_data_and_receipt_encoding =
Apply_results.operation_data_and_metadata_encoding
@ -56,21 +64,28 @@ type operation = Alpha_context.packed_operation = {
let acceptable_passes = Alpha_context.Operation.acceptable_passes
let max_block_length =
Alpha_context.Block_header.max_header_length
let max_block_length = Alpha_context.Block_header.max_header_length
let max_operation_data_length =
Alpha_context.Constants.max_operation_data_length
let validation_passes =
let max_anonymous_operations =
Alpha_context.Constants.max_revelations_per_block +
(* allow 100 wallet activations or denunciations per block *) 100 in
Updater.[ { max_size = 32 * 1024 ; max_op = Some 32 } ; (* 32 endorsements *)
{ max_size = 32 * 1024 ; max_op = None } ; (* 32k of voting operations *)
{ max_size = max_anonymous_operations * 1024 ;
max_op = Some max_anonymous_operations } ;
{ max_size = 512 * 1024 ; max_op = None } ] (* 512kB *)
Alpha_context.Constants.max_revelations_per_block
+ (* allow 100 wallet activations or denunciations per block *) 100
in
Updater.
[ {max_size = 32 * 1024; max_op = Some 32};
(* 32 endorsements *)
{max_size = 32 * 1024; max_op = None};
(* 32k of voting operations *)
{
max_size = max_anonymous_operations * 1024;
max_op = Some max_anonymous_operations;
};
{max_size = 512 * 1024; max_op = None} ]
(* 512kB *)
let rpc_services =
Alpha_services.register () ;
@ -87,9 +102,7 @@ type validation_mode =
baker : Alpha_context.public_key_hash;
block_delay : Alpha_context.Period.t;
}
| Partial_construction of {
predecessor : Block_hash.t ;
}
| Partial_construction of {predecessor : Block_hash.t}
| Full_construction of {
predecessor : Block_hash.t;
protocol_data : Alpha_context.Block_header.contents;
@ -97,85 +110,80 @@ type validation_mode =
block_delay : Alpha_context.Period.t;
}
type validation_state =
{ mode : validation_mode ;
type validation_state = {
mode : validation_mode;
chain_id : Chain_id.t;
ctxt : Alpha_context.t;
op_count : int;
}
let current_context { ctxt ; _ } =
return (Alpha_context.finalize ctxt).context
let current_context {ctxt; _} = return (Alpha_context.finalize ctxt).context
let begin_partial_application
~chain_id
~ancestor_context:ctxt
~predecessor_timestamp
~predecessor_fitness
let begin_partial_application ~chain_id ~ancestor_context:ctxt
~predecessor_timestamp ~predecessor_fitness
(block_header : Alpha_context.Block_header.t) =
let level = block_header.shell.level in
let fitness = predecessor_fitness in
let timestamp = block_header.shell.timestamp in
Alpha_context.prepare ~level ~predecessor_timestamp ~timestamp ~fitness ctxt >>=? fun ctxt ->
Apply.begin_application
ctxt chain_id block_header predecessor_timestamp >>=? fun (ctxt, baker, block_delay) ->
Alpha_context.prepare ~level ~predecessor_timestamp ~timestamp ~fitness ctxt
>>=? fun ctxt ->
Apply.begin_application ctxt chain_id block_header predecessor_timestamp
>>=? fun (ctxt, baker, block_delay) ->
let mode =
Partial_application
{ block_header ; baker = Signature.Public_key.hash baker ; block_delay } in
{block_header; baker = Signature.Public_key.hash baker; block_delay}
in
return {mode; chain_id; ctxt; op_count = 0}
let begin_application
~chain_id
~predecessor_context:ctxt
~predecessor_timestamp
~predecessor_fitness
let begin_application ~chain_id ~predecessor_context:ctxt
~predecessor_timestamp ~predecessor_fitness
(block_header : Alpha_context.Block_header.t) =
let level = block_header.shell.level in
let fitness = predecessor_fitness in
let timestamp = block_header.shell.timestamp in
Alpha_context.prepare ~level ~predecessor_timestamp ~timestamp ~fitness ctxt >>=? fun ctxt ->
Apply.begin_application
ctxt chain_id block_header predecessor_timestamp >>=? fun (ctxt, baker, block_delay) ->
Alpha_context.prepare ~level ~predecessor_timestamp ~timestamp ~fitness ctxt
>>=? fun ctxt ->
Apply.begin_application ctxt chain_id block_header predecessor_timestamp
>>=? fun (ctxt, baker, block_delay) ->
let mode =
Application { block_header ; baker = Signature.Public_key.hash baker ; block_delay } in
Application
{block_header; baker = Signature.Public_key.hash baker; block_delay}
in
return {mode; chain_id; ctxt; op_count = 0}
let begin_construction
~chain_id
~predecessor_context:ctxt
~predecessor_timestamp
~predecessor_level:pred_level
~predecessor_fitness:pred_fitness
~predecessor
~timestamp
?(protocol_data : block_header_data option)
() =
let begin_construction ~chain_id ~predecessor_context:ctxt
~predecessor_timestamp ~predecessor_level:pred_level
~predecessor_fitness:pred_fitness ~predecessor ~timestamp
?(protocol_data : block_header_data option) () =
let level = Int32.succ pred_level in
let fitness = pred_fitness in
Alpha_context.prepare ~level ~predecessor_timestamp ~timestamp ~fitness ctxt >>=? fun ctxt ->
begin
match protocol_data with
Alpha_context.prepare ~level ~predecessor_timestamp ~timestamp ~fitness ctxt
>>=? fun ctxt ->
( match protocol_data with
| None ->
Apply.begin_partial_construction ctxt >>=? fun ctxt ->
Apply.begin_partial_construction ctxt
>>=? fun ctxt ->
let mode = Partial_construction {predecessor} in
return (mode, ctxt)
| Some proto_header ->
Apply.begin_full_construction
ctxt predecessor_timestamp
proto_header.contents >>=? fun (ctxt, protocol_data, baker, block_delay) ->
ctxt
predecessor_timestamp
proto_header.contents
>>=? fun (ctxt, protocol_data, baker, block_delay) ->
let mode =
let baker = Signature.Public_key.hash baker in
Full_construction { predecessor ; baker ; protocol_data ; block_delay } in
return (mode, ctxt)
end >>=? fun (mode, ctxt) ->
return { mode ; chain_id ; ctxt ; op_count = 0 }
Full_construction {predecessor; baker; protocol_data; block_delay}
in
return (mode, ctxt) )
>>=? fun (mode, ctxt) -> return {mode; chain_id; ctxt; op_count = 0}
let apply_operation
({ mode ; chain_id ; ctxt ; op_count ; _ } as data)
let apply_operation ({mode; chain_id; ctxt; op_count; _} as data)
(operation : Alpha_context.packed_operation) =
match mode with
| Partial_application _ when
not (List.exists
| Partial_application _
when not
(List.exists
(Compare.Int.equal 0)
(Alpha_context.Operation.acceptable_passes operation)) ->
(* Multipass validation only considers operations in pass 0. *)
@ -184,20 +192,25 @@ let apply_operation
| _ ->
let {shell; protocol_data = Operation_data protocol_data} = operation in
let operation : _ Alpha_context.operation = {shell; protocol_data} in
let predecessor, baker =
let (predecessor, baker) =
match mode with
| Partial_application
{block_header = {shell = {predecessor; _}; _}; baker}
| Application
{ block_header = { shell = { predecessor ; _ } ; _ } ; baker }
| Full_construction { predecessor ; baker ; _ }
-> predecessor, baker
| Partial_construction { predecessor }
-> predecessor, Signature.Public_key_hash.zero
| Application {block_header = {shell = {predecessor; _}; _}; baker}
| Full_construction {predecessor; baker; _} ->
(predecessor, baker)
| Partial_construction {predecessor} ->
(predecessor, Signature.Public_key_hash.zero)
in
Apply.apply_operation ctxt chain_id Optimized predecessor baker
Apply.apply_operation
ctxt
chain_id
Optimized
predecessor
baker
(Alpha_context.Operation.hash operation)
operation >>=? fun (ctxt, result) ->
operation
>>=? fun (ctxt, result) ->
let op_count = op_count + 1 in
return ({data with ctxt; op_count}, Operation_metadata result)
@ -205,41 +218,61 @@ let finalize_block { mode ; ctxt ; op_count } =
match mode with
| Partial_construction _ ->
let level = Alpha_context.Level.current ctxt in
Alpha_context.Vote.get_current_period_kind ctxt >>=? fun voting_period_kind ->
Alpha_context.Vote.get_current_period_kind ctxt
>>=? fun voting_period_kind ->
let baker = Signature.Public_key_hash.zero in
Signature.Public_key_hash.Map.fold
(fun delegate deposit ctxt ->
ctxt >>=? fun ctxt ->
ctxt
>>=? fun ctxt ->
Alpha_context.Delegate.freeze_deposit ctxt delegate deposit)
(Alpha_context.get_deposits ctxt)
(return ctxt) >>=? fun ctxt ->
(return ctxt)
>>=? fun ctxt ->
let ctxt = Alpha_context.finalize ctxt in
return (ctxt, Apply_results.{ baker ;
return
( ctxt,
Apply_results.
{
baker;
level;
voting_period_kind;
nonce_hash = None;
consumed_gas = Z.zero;
deactivated = [];
balance_updates = []})
balance_updates = [];
} )
| Partial_application {block_header; baker; block_delay} ->
let level = Alpha_context.Level.current ctxt in
let included_endorsements = Alpha_context.included_endorsements ctxt in
Apply.check_minimum_endorsements ctxt
Apply.check_minimum_endorsements
ctxt
block_header.protocol_data.contents
block_delay included_endorsements >>=? fun () ->
Alpha_context.Vote.get_current_period_kind ctxt >>=? fun voting_period_kind ->
block_delay
included_endorsements
>>=? fun () ->
Alpha_context.Vote.get_current_period_kind ctxt
>>=? fun voting_period_kind ->
let ctxt = Alpha_context.finalize ctxt in
return (ctxt, Apply_results.{ baker ;
return
( ctxt,
Apply_results.
{
baker;
level;
voting_period_kind;
nonce_hash = None;
consumed_gas = Z.zero;
deactivated = [];
balance_updates = []})
balance_updates = [];
} )
| Application
{ baker ; block_delay ; block_header = { protocol_data = { contents = protocol_data ; _ } ; _ } }
{ baker;
block_delay;
block_header = {protocol_data = {contents = protocol_data; _}; _} }
| Full_construction {protocol_data; baker; block_delay; _} ->
Apply.finalize_application ctxt protocol_data baker ~block_delay >>=? fun (ctxt, receipt) ->
Apply.finalize_application ctxt protocol_data baker ~block_delay
>>=? fun (ctxt, receipt) ->
let level = Alpha_context.Level.current ctxt in
let priority = protocol_data.priority in
let raw_level = Alpha_context.Raw_level.to_int32 level.level in
@ -247,69 +280,101 @@ let finalize_block { mode ; ctxt ; op_count } =
let commit_message =
Format.asprintf
"lvl %ld, fit 1:%Ld, prio %d, %d ops"
raw_level fitness priority op_count in
raw_level
fitness
priority
op_count
in
let ctxt = Alpha_context.finalize ~commit_message ctxt in
return (ctxt, receipt)
let compare_operations op1 op2 =
let open Alpha_context in
let Operation_data op1 = op1.protocol_data in
let Operation_data op2 = op2.protocol_data in
match op1.contents, op2.contents with
| Single (Endorsement _), Single (Endorsement _) -> 0
| _, Single (Endorsement _) -> 1
| Single (Endorsement _), _ -> -1
| Single (Seed_nonce_revelation _), Single (Seed_nonce_revelation _) -> 0
| _, Single (Seed_nonce_revelation _) -> 1
| Single (Seed_nonce_revelation _), _ -> -1
| Single (Double_endorsement_evidence _), Single (Double_endorsement_evidence _) -> 0
| _, Single (Double_endorsement_evidence _) -> 1
| Single (Double_endorsement_evidence _), _ -> -1
| Single (Double_baking_evidence _), Single (Double_baking_evidence _) -> 0
| _, Single (Double_baking_evidence _) -> 1
| Single (Double_baking_evidence _), _ -> -1
| Single (Activate_account _), Single (Activate_account _) -> 0
| _, Single (Activate_account _) -> 1
| Single (Activate_account _), _ -> -1
| Single (Proposals _), Single (Proposals _) -> 0
| _, Single (Proposals _) -> 1
| Single (Proposals _), _ -> -1
| Single (Ballot _), Single (Ballot _) -> 0
| _, Single (Ballot _) -> 1
| Single (Ballot _), _ -> -1
let (Operation_data op1) = op1.protocol_data in
let (Operation_data op2) = op2.protocol_data in
match (op1.contents, op2.contents) with
| (Single (Endorsement _), Single (Endorsement _)) ->
0
| (_, Single (Endorsement _)) ->
1
| (Single (Endorsement _), _) ->
-1
| (Single (Seed_nonce_revelation _), Single (Seed_nonce_revelation _)) ->
0
| (_, Single (Seed_nonce_revelation _)) ->
1
| (Single (Seed_nonce_revelation _), _) ->
-1
| ( Single (Double_endorsement_evidence _),
Single (Double_endorsement_evidence _) ) ->
0
| (_, Single (Double_endorsement_evidence _)) ->
1
| (Single (Double_endorsement_evidence _), _) ->
-1
| (Single (Double_baking_evidence _), Single (Double_baking_evidence _)) ->
0
| (_, Single (Double_baking_evidence _)) ->
1
| (Single (Double_baking_evidence _), _) ->
-1
| (Single (Activate_account _), Single (Activate_account _)) ->
0
| (_, Single (Activate_account _)) ->
1
| (Single (Activate_account _), _) ->
-1
| (Single (Proposals _), Single (Proposals _)) ->
0
| (_, Single (Proposals _)) ->
1
| (Single (Proposals _), _) ->
-1
| (Single (Ballot _), Single (Ballot _)) ->
0
| (_, Single (Ballot _)) ->
1
| (Single (Ballot _), _) ->
-1
(* Manager operations with smaller counter are pre-validated first. *)
| Single (Manager_operation op1), Single (Manager_operation op2) ->
| (Single (Manager_operation op1), Single (Manager_operation op2)) ->
Z.compare op1.counter op2.counter
| Cons (Manager_operation op1, _), Single (Manager_operation op2) ->
| (Cons (Manager_operation op1, _), Single (Manager_operation op2)) ->
Z.compare op1.counter op2.counter
| Single (Manager_operation op1), Cons (Manager_operation op2, _) ->
| (Single (Manager_operation op1), Cons (Manager_operation op2, _)) ->
Z.compare op1.counter op2.counter
| Cons (Manager_operation op1, _), Cons (Manager_operation op2, _) ->
| (Cons (Manager_operation op1, _), Cons (Manager_operation op2, _)) ->
Z.compare op1.counter op2.counter
let init ctxt block_header =
let level = block_header.Block_header.level in
let fitness = block_header.fitness in
let timestamp = block_header.timestamp in
let typecheck (ctxt:Alpha_context.context) (script:Alpha_context.Script.t) =
Script_ir_translator.parse_script ctxt ~legacy:false script >>=? fun (Ex_script parsed_script, ctxt) ->
Script_ir_translator.extract_big_map_diff ctxt Optimized parsed_script.storage_type parsed_script.storage
let typecheck (ctxt : Alpha_context.context)
(script : Alpha_context.Script.t) =
Script_ir_translator.parse_script ctxt ~legacy:false script
>>=? fun (Ex_script parsed_script, ctxt) ->
Script_ir_translator.extract_big_map_diff
ctxt
Optimized
parsed_script.storage_type
parsed_script.storage
~to_duplicate:Script_ir_translator.no_big_map_id
~to_update:Script_ir_translator.no_big_map_id
~temporary:false >>=? fun (storage, big_map_diff, ctxt) ->
Script_ir_translator.unparse_data ctxt Optimized parsed_script.storage_type storage >>=? fun (storage, ctxt) ->
let storage = Alpha_context.Script.lazy_expr (Micheline.strip_locations storage) in
~temporary:false
>>=? fun (storage, big_map_diff, ctxt) ->
Script_ir_translator.unparse_data
ctxt
Optimized
parsed_script.storage_type
storage
>>=? fun (storage, ctxt) ->
let storage =
Alpha_context.Script.lazy_expr (Micheline.strip_locations storage)
in
return (({script with storage}, big_map_diff), ctxt)
in
Alpha_context.prepare_first_block
~typecheck
~level ~timestamp ~fitness ctxt >>=? fun ctxt ->
return (Alpha_context.finalize ctxt)
(* Vanity nonce: 415767323 *)
Alpha_context.prepare_first_block ~typecheck ~level ~timestamp ~fitness ctxt
>>=? fun ctxt -> return (Alpha_context.finalize ctxt)
(* Vanity nonce: 0050006865723388 *)

View File

@ -36,9 +36,7 @@ type validation_mode =
baker : Alpha_context.public_key_hash;
block_delay : Alpha_context.Period.t;
}
| Partial_construction of {
predecessor : Block_hash.t ;
}
| Partial_construction of {predecessor : Block_hash.t}
| Full_construction of {
predecessor : Block_hash.t;
protocol_data : Alpha_context.Block_header.contents;
@ -46,8 +44,8 @@ type validation_mode =
block_delay : Alpha_context.Period.t;
}
type validation_state =
{ mode : validation_mode ;
type validation_state = {
mode : validation_mode;
chain_id : Chain_id.t;
ctxt : Alpha_context.t;
op_count : int;
@ -60,7 +58,8 @@ type operation = Alpha_context.packed_operation = {
protocol_data : operation_data;
}
include Updater.PROTOCOL
include
Updater.PROTOCOL
with type block_header_data = Alpha_context.Block_header.protocol_data
and type block_header_metadata = Apply_results.block_metadata
and type block_header = Alpha_context.Block_header.t

View File

@ -34,27 +34,19 @@ type t = manager_key
open Data_encoding
let hash_case tag =
case tag
case
tag
~title:"Public_key_hash"
Signature.Public_key_hash.encoding
(function
| Hash hash -> Some hash
| _ -> None)
(function Hash hash -> Some hash | _ -> None)
(fun hash -> Hash hash)
let pubkey_case tag =
case tag
case
tag
~title:"Public_key"
Signature.Public_key.encoding
(function
| Public_key hash -> Some hash
| _ -> None)
(function Public_key hash -> Some hash | _ -> None)
(fun hash -> Public_key hash)
let encoding =
union [
hash_case (Tag 0) ;
pubkey_case (Tag 1) ;
]
let encoding = union [hash_case (Tag 0); pubkey_case (Tag 1)]

View File

@ -27,93 +27,108 @@ open Alpha_context
open Gas
module Cost_of = struct
let log2 =
let rec help acc = function
| 0 -> acc
| n -> help (acc + 1) (n / 2)
in help 1
let rec help acc = function 0 -> acc | n -> help (acc + 1) (n / 2) in
help 1
let z_bytes (z : Z.t) =
let bits = Z.numbits z in
(7 + bits) / 8
let int_bytes (z : 'a Script_int.num) =
z_bytes (Script_int.to_zint z)
let int_bytes (z : 'a Script_int.num) = z_bytes (Script_int.to_zint z)
let timestamp_bytes (t : Script_timestamp.t) =
let z = Script_timestamp.to_zint t in
z_bytes z
(* For now, returns size in bytes, but this could get more complicated... *)
let rec size_of_comparable : type a b. (a, b) Script_typed_ir.comparable_struct -> a -> int =
let rec size_of_comparable :
type a b. (a, b) Script_typed_ir.comparable_struct -> a -> int =
fun wit v ->
match wit with
| Int_key _ -> int_bytes v
| Nat_key _ -> int_bytes v
| String_key _ -> String.length v
| Bytes_key _ -> MBytes.length v
| Bool_key _ -> 8
| Key_hash_key _ -> Signature.Public_key_hash.size
| Timestamp_key _ -> timestamp_bytes v
| Address_key _ -> Signature.Public_key_hash.size
| Mutez_key _ -> 8
| Int_key _ ->
int_bytes v
| Nat_key _ ->
int_bytes v
| String_key _ ->
String.length v
| Bytes_key _ ->
MBytes.length v
| Bool_key _ ->
8
| Key_hash_key _ ->
Signature.Public_key_hash.size
| Timestamp_key _ ->
timestamp_bytes v
| Address_key _ ->
Signature.Public_key_hash.size
| Mutez_key _ ->
8
| Pair_key ((l, _), (r, _), _) ->
let (lval, rval) = v in
size_of_comparable l lval + size_of_comparable r rval
let string length =
alloc_bytes_cost length
let string length = alloc_bytes_cost length
let bytes length =
alloc_mbytes_cost length
let bytes length = alloc_mbytes_cost length
let manager_operation = step_cost 10_000
module Legacy = struct
let zint z =
alloc_bits_cost (Z.numbits z)
let zint z = alloc_bits_cost (Z.numbits z)
let set_to_list : type item. item Script_typed_ir.set -> cost
= fun (module Box) ->
alloc_cost @@ Pervasives.(Box.size * 2)
let set_to_list : type item. item Script_typed_ir.set -> cost =
fun (module Box) -> alloc_cost @@ Pervasives.(Box.size * 2)
let map_to_list : type key value. (key, value) Script_typed_ir.map -> cost
= fun (module Box) ->
=
fun (module Box) ->
let size = snd Box.boxed in
3 *@ alloc_cost size
let z_to_int64 = step_cost 2 +@ alloc_cost 1
let hash data len = 10 *@ step_cost (MBytes.length data) +@ bytes len
let hash data len = (10 *@ step_cost (MBytes.length data)) +@ bytes len
let set_access : type elt. elt -> elt Script_typed_ir.set -> int
= fun _key (module Box) ->
log2 @@ Box.size
let set_access : type elt. elt -> elt Script_typed_ir.set -> int =
fun _key (module Box) -> log2 @@ Box.size
let set_update key _presence set =
set_access key set *@ alloc_cost 3
let set_update key _presence set = set_access key set *@ alloc_cost 3
end
module Interpreter = struct
let cycle = atomic_step_cost 10
let nop = free
let stack_op = atomic_step_cost 10
let push = atomic_step_cost 10
let wrap = atomic_step_cost 10
let variant_no_data = atomic_step_cost 10
let branch = atomic_step_cost 10
let pair = atomic_step_cost 10
let pair_access = atomic_step_cost 10
let cons = atomic_step_cost 10
let loop_size = atomic_step_cost 5
let loop_cycle = atomic_step_cost 10
let loop_iter = atomic_step_cost 20
let loop_map = atomic_step_cost 30
let empty_set = atomic_step_cost 10
let set_to_list : type elt. elt Script_typed_ir.set -> cost =
fun (module Box) ->
atomic_step_cost (Box.size * 20)
fun (module Box) -> atomic_step_cost (Box.size * 20)
let set_mem : type elt. elt -> elt Script_typed_ir.set -> cost =
fun elt (module Box) ->
@ -126,23 +141,30 @@ module Cost_of = struct
atomic_step_cost ((1 + (elt_bytes / 82)) * log2 Box.size)
let set_size = atomic_step_cost 10
let empty_map = atomic_step_cost 10
let map_to_list : type key value. (key, value) Script_typed_ir.map -> cost =
let map_to_list : type key value. (key, value) Script_typed_ir.map -> cost
=
fun (module Box) ->
let size = snd Box.boxed in
atomic_step_cost (size * 20)
let map_access : type key value. key -> (key, value) Script_typed_ir.map -> cost
= fun key (module Box) ->
let map_access :
type key value. key -> (key, value) Script_typed_ir.map -> cost =
fun key (module Box) ->
let map_card = snd Box.boxed in
let key_bytes = size_of_comparable Box.key_ty key in
atomic_step_cost ((1 + (key_bytes / 70)) * log2 map_card)
let map_mem = map_access
let map_get = map_access
let map_update : type key value. key -> value option -> (key, value) Script_typed_ir.map -> cost
= fun key _value (module Box) ->
let map_update :
type key value.
key -> value option -> (key, value) Script_typed_ir.map -> cost =
fun key _value (module Box) ->
let map_card = snd Box.boxed in
let key_bytes = size_of_comparable Box.key_ty key in
atomic_step_cost ((1 + (key_bytes / 38)) * log2 map_card)
@ -153,16 +175,16 @@ module Cost_of = struct
let bytes1 = timestamp_bytes t1 in
let bytes2 = int_bytes t2 in
atomic_step_cost (51 + (Compare.Int.max bytes1 bytes2 / 62))
let sub_timestamp = add_timestamp
let diff_timestamps (t1 : Script_timestamp.t) (t2 : Script_timestamp.t) =
let bytes1 = timestamp_bytes t1 in
let bytes2 = timestamp_bytes t2 in
atomic_step_cost (51 + (Compare.Int.max bytes1 bytes2 / 62))
let rec concat_loop l acc =
match l with
| [] -> 30
| _ :: tl -> concat_loop tl (acc + 30)
match l with [] -> 30 | _ :: tl -> concat_loop tl (acc + 30)
let concat_string string_list =
atomic_step_cost (concat_loop string_list 0)
@ -170,19 +192,28 @@ module Cost_of = struct
let slice_string string_length =
atomic_step_cost (40 + (string_length / 70))
let concat_bytes bytes_list =
atomic_step_cost (concat_loop bytes_list 0)
let concat_bytes bytes_list = atomic_step_cost (concat_loop bytes_list 0)
let int64_op = atomic_step_cost 61
let z_to_int64 = atomic_step_cost 20
let int64_to_z = atomic_step_cost 20
let bool_binop _ _ = atomic_step_cost 10
let bool_unop _ = atomic_step_cost 10
let abs int = atomic_step_cost (61 + ((int_bytes int) / 70))
let abs int = atomic_step_cost (61 + (int_bytes int / 70))
let int _int = free
let neg = abs
let add i1 i2 = atomic_step_cost (51 + (Compare.Int.max (int_bytes i1) (int_bytes i2) / 62))
let add i1 i2 =
atomic_step_cost
(51 + (Compare.Int.max (int_bytes i1) (int_bytes i2) / 62))
let sub = add
let mul i1 i2 =
@ -198,303 +229,537 @@ module Cost_of = struct
atomic_step_cost (51 + (cost / 3151))
let shift_left _i _shift_bits = atomic_step_cost 30
let shift_right _i _shift_bits = atomic_step_cost 30
let logor i1 i2 =
let bytes1 = int_bytes i1 in
let bytes2 = int_bytes i2 in
atomic_step_cost (51 + ((Compare.Int.max bytes1 bytes2) / 70))
atomic_step_cost (51 + (Compare.Int.max bytes1 bytes2 / 70))
let logand i1 i2 =
let bytes1 = int_bytes i1 in
let bytes2 = int_bytes i2 in
atomic_step_cost (51 + ((Compare.Int.min bytes1 bytes2) / 70))
atomic_step_cost (51 + (Compare.Int.min bytes1 bytes2 / 70))
let logxor = logor
let lognot i = atomic_step_cost (51 + ((int_bytes i) / 20))
let lognot i = atomic_step_cost (51 + (int_bytes i / 20))
let exec = atomic_step_cost 10
let compare_bool _ _ = atomic_step_cost 30
let compare_string s1 s2 =
let bytes1 = String.length s1 in
let bytes2 = String.length s2 in
atomic_step_cost (30 + ((Compare.Int.min bytes1 bytes2) / 123))
atomic_step_cost (30 + (Compare.Int.min bytes1 bytes2 / 123))
let compare_bytes b1 b2 =
let bytes1 = MBytes.length b1 in
let bytes2 = MBytes.length b2 in
atomic_step_cost (30 + ((Compare.Int.min bytes1 bytes2) / 123))
atomic_step_cost (30 + (Compare.Int.min bytes1 bytes2 / 123))
let compare_tez _ _ = atomic_step_cost 30
let compare_zint i1 i2 =
atomic_step_cost (51 + ((Compare.Int.min (int_bytes i1) (int_bytes i2)) / 82))
atomic_step_cost
(51 + (Compare.Int.min (int_bytes i1) (int_bytes i2) / 82))
let compare_key_hash _ _ = atomic_step_cost 92
let compare_timestamp t1 t2 =
let bytes1 = timestamp_bytes t1 in
let bytes2 = timestamp_bytes t2 in
atomic_step_cost (51 + ((Compare.Int.min bytes1 bytes2) / 82))
atomic_step_cost (51 + (Compare.Int.min bytes1 bytes2 / 82))
let compare_address _ _ = atomic_step_cost 92
let compare_res = atomic_step_cost 30
let unpack_failed bytes =
(* We cannot instrument failed deserialization,
so we take worst case fees: a set of size 1 bytes values. *)
let len = MBytes.length bytes in
(len *@ alloc_mbytes_cost 1) +@
(len *@ (log2 len *@ (alloc_cost 3 +@ step_cost 1)))
(len *@ alloc_mbytes_cost 1)
+@ (len *@ (log2 len *@ (alloc_cost 3 +@ step_cost 1)))
let address = atomic_step_cost 10
let contract = step_cost 10000
let transfer = step_cost 10
let create_account = step_cost 10
let create_contract = step_cost 10
let implicit_account = step_cost 10
let set_delegate = step_cost 10 +@ write_bytes_cost (Z.of_int 32)
let balance = atomic_step_cost 10
let now = atomic_step_cost 10
let check_signature_secp256k1 bytes = atomic_step_cost (10342 + (bytes / 5))
let check_signature_ed25519 bytes = atomic_step_cost (36864 + (bytes / 5))
let check_signature_p256 bytes = atomic_step_cost (36864 + (bytes / 5))
let check_signature (pkey : Signature.public_key) bytes =
match pkey with
| Ed25519 _ -> check_signature_ed25519 (MBytes.length bytes)
| Secp256k1 _ -> check_signature_secp256k1 (MBytes.length bytes)
| P256 _ -> check_signature_p256 (MBytes.length bytes)
| Ed25519 _ ->
check_signature_ed25519 (MBytes.length bytes)
| Secp256k1 _ ->
check_signature_secp256k1 (MBytes.length bytes)
| P256 _ ->
check_signature_p256 (MBytes.length bytes)
let hash_key = atomic_step_cost 30
let hash_blake2b b = atomic_step_cost (102 + ((MBytes.length b) / 5))
let hash_sha256 b = atomic_step_cost (409 + (MBytes.length b))
let hash_blake2b b = atomic_step_cost (102 + (MBytes.length b / 5))
let hash_sha256 b = atomic_step_cost (409 + MBytes.length b)
let hash_sha512 b =
let bytes = MBytes.length b in atomic_step_cost (409 + ((bytes lsr 1) + (bytes lsr 4)))
let bytes = MBytes.length b in
atomic_step_cost (409 + ((bytes lsr 1) + (bytes lsr 4)))
let steps_to_quota = atomic_step_cost 10
let source = atomic_step_cost 10
let self = atomic_step_cost 10
let amount = atomic_step_cost 10
let chain_id = step_cost 1
let stack_n_op n = atomic_step_cost (20 + (((n lsr 1) + (n lsr 2)) + (n lsr 4)))
let stack_n_op n =
atomic_step_cost (20 + ((n lsr 1) + (n lsr 2) + (n lsr 4)))
let apply = alloc_cost 8 +@ step_cost 1
let rec compare : type a s. (a, s) Script_typed_ir.comparable_struct -> a -> a -> cost = fun ty x y ->
let rec compare :
type a s. (a, s) Script_typed_ir.comparable_struct -> a -> a -> cost =
fun ty x y ->
match ty with
| Bool_key _ -> compare_bool x y
| String_key _ -> compare_string x y
| Bytes_key _ -> compare_bytes x y
| Mutez_key _ -> compare_tez x y
| Int_key _ -> compare_zint x y
| Nat_key _ -> compare_zint x y
| Key_hash_key _ -> compare_key_hash x y
| Timestamp_key _ -> compare_timestamp x y
| Address_key _ -> compare_address x y
| Bool_key _ ->
compare_bool x y
| String_key _ ->
compare_string x y
| Bytes_key _ ->
compare_bytes x y
| Mutez_key _ ->
compare_tez x y
| Int_key _ ->
compare_zint x y
| Nat_key _ ->
compare_zint x y
| Key_hash_key _ ->
compare_key_hash x y
| Timestamp_key _ ->
compare_timestamp x y
| Address_key _ ->
compare_address x y
| Pair_key ((tl, _), (tr, _), _) ->
(* Reasonable over-approximation of the cost of lexicographic comparison. *)
let (xl, xr) = x and (yl, yr) = y in
compare tl xl yl +@ compare tr xr yr
end
module Typechecking = struct
let cycle = step_cost 1
let bool = free
let unit = free
let string = string
let bytes = bytes
let z = Legacy.zint
let int_of_string str =
alloc_cost @@ (Pervasives.(/) (String.length str) 5)
alloc_cost @@ Pervasives.( / ) (String.length str) 5
let tez = step_cost 1 +@ alloc_cost 1
let string_timestamp = step_cost 3 +@ alloc_cost 3
let key = step_cost 3 +@ alloc_cost 3
let key_hash = step_cost 1 +@ alloc_cost 1
let signature = step_cost 1 +@ alloc_cost 1
let chain_id = step_cost 1 +@ alloc_cost 1
let contract = step_cost 5
let get_script = step_cost 20 +@ alloc_cost 5
let contract_exists = step_cost 15 +@ alloc_cost 5
let pair = alloc_cost 2
let union = alloc_cost 1
let lambda = alloc_cost 5 +@ step_cost 3
let some = alloc_cost 1
let none = alloc_cost 0
let list_element = alloc_cost 2 +@ step_cost 1
let set_element size = log2 size *@ (alloc_cost 3 +@ step_cost 2)
let map_element size = log2 size *@ (alloc_cost 4 +@ step_cost 2)
let primitive_type = alloc_cost 1
let one_arg_type = alloc_cost 2
let two_arg_type = alloc_cost 3
let operation b = bytes b
let type_ nb_args = alloc_cost (nb_args + 1)
(* Cost of parsing instruction, is cost of allocation of
constructor + cost of contructor parameters + cost of
allocation on the stack type *)
let instr
: type b a. (b, a) Script_typed_ir.instr -> cost
= fun i ->
let instr : type b a. (b, a) Script_typed_ir.instr -> cost =
fun i ->
let open Script_typed_ir in
alloc_cost 1 +@ (* cost of allocation of constructor *)
alloc_cost 1
+@
(* cost of allocation of constructor *)
match i with
| Drop -> alloc_cost 0
| Dup -> alloc_cost 1
| Swap -> alloc_cost 0
| Const _ -> alloc_cost 1
| Cons_pair -> alloc_cost 2
| Car -> alloc_cost 1
| Cdr -> alloc_cost 1
| Cons_some -> alloc_cost 2
| Cons_none _ -> alloc_cost 3
| If_none _ -> alloc_cost 2
| Left -> alloc_cost 3
| Right -> alloc_cost 3
| If_left _ -> alloc_cost 2
| Cons_list -> alloc_cost 1
| Nil -> alloc_cost 1
| If_cons _ -> alloc_cost 2
| List_map _ -> alloc_cost 5
| List_iter _ -> alloc_cost 4
| List_size -> alloc_cost 1
| Empty_set _ -> alloc_cost 1
| Set_iter _ -> alloc_cost 4
| Set_mem -> alloc_cost 1
| Set_update -> alloc_cost 1
| Set_size -> alloc_cost 1
| Empty_map _ -> alloc_cost 2
| Map_map _ -> alloc_cost 5
| Map_iter _ -> alloc_cost 4
| Map_mem -> alloc_cost 1
| Map_get -> alloc_cost 1
| Map_update -> alloc_cost 1
| Map_size -> alloc_cost 1
| Empty_big_map _ -> alloc_cost 2
| Big_map_mem -> alloc_cost 1
| Big_map_get -> alloc_cost 1
| Big_map_update -> alloc_cost 1
| Concat_string -> alloc_cost 1
| Concat_string_pair -> alloc_cost 1
| Concat_bytes -> alloc_cost 1
| Concat_bytes_pair -> alloc_cost 1
| Slice_string -> alloc_cost 1
| Slice_bytes -> alloc_cost 1
| String_size -> alloc_cost 1
| Bytes_size -> alloc_cost 1
| Add_seconds_to_timestamp -> alloc_cost 1
| Add_timestamp_to_seconds -> alloc_cost 1
| Sub_timestamp_seconds -> alloc_cost 1
| Diff_timestamps -> alloc_cost 1
| Add_tez -> alloc_cost 1
| Sub_tez -> alloc_cost 1
| Mul_teznat -> alloc_cost 1
| Mul_nattez -> alloc_cost 1
| Ediv_teznat -> alloc_cost 1
| Ediv_tez -> alloc_cost 1
| Or -> alloc_cost 1
| And -> alloc_cost 1
| Xor -> alloc_cost 1
| Not -> alloc_cost 1
| Is_nat -> alloc_cost 1
| Neg_nat -> alloc_cost 1
| Neg_int -> alloc_cost 1
| Abs_int -> alloc_cost 1
| Int_nat -> alloc_cost 1
| Add_intint -> alloc_cost 1
| Add_intnat -> alloc_cost 1
| Add_natint -> alloc_cost 1
| Add_natnat -> alloc_cost 1
| Sub_int -> alloc_cost 1
| Mul_intint -> alloc_cost 1
| Mul_intnat -> alloc_cost 1
| Mul_natint -> alloc_cost 1
| Mul_natnat -> alloc_cost 1
| Ediv_intint -> alloc_cost 1
| Ediv_intnat -> alloc_cost 1
| Ediv_natint -> alloc_cost 1
| Ediv_natnat -> alloc_cost 1
| Lsl_nat -> alloc_cost 1
| Lsr_nat -> alloc_cost 1
| Or_nat -> alloc_cost 1
| And_nat -> alloc_cost 1
| And_int_nat -> alloc_cost 1
| Xor_nat -> alloc_cost 1
| Not_nat -> alloc_cost 1
| Not_int -> alloc_cost 1
| Seq _ -> alloc_cost 8
| If _ -> alloc_cost 8
| Loop _ -> alloc_cost 4
| Loop_left _ -> alloc_cost 5
| Dip _ -> alloc_cost 4
| Exec -> alloc_cost 1
| Apply _ -> alloc_cost 1
| Lambda _ -> alloc_cost 2
| Failwith _ -> alloc_cost 1
| Nop -> alloc_cost 0
| Compare _ -> alloc_cost 1
| Eq -> alloc_cost 1
| Neq -> alloc_cost 1
| Lt -> alloc_cost 1
| Gt -> alloc_cost 1
| Le -> alloc_cost 1
| Ge -> alloc_cost 1
| Address -> alloc_cost 1
| Contract _ -> alloc_cost 2
| Transfer_tokens -> alloc_cost 1
| Create_account -> alloc_cost 2
| Implicit_account -> alloc_cost 1
| Create_contract _ -> alloc_cost 8
| Drop ->
alloc_cost 0
| Dup ->
alloc_cost 1
| Swap ->
alloc_cost 0
| Const _ ->
alloc_cost 1
| Cons_pair ->
alloc_cost 2
| Car ->
alloc_cost 1
| Cdr ->
alloc_cost 1
| Cons_some ->
alloc_cost 2
| Cons_none _ ->
alloc_cost 3
| If_none _ ->
alloc_cost 2
| Left ->
alloc_cost 3
| Right ->
alloc_cost 3
| If_left _ ->
alloc_cost 2
| Cons_list ->
alloc_cost 1
| Nil ->
alloc_cost 1
| If_cons _ ->
alloc_cost 2
| List_map _ ->
alloc_cost 5
| List_iter _ ->
alloc_cost 4
| List_size ->
alloc_cost 1
| Empty_set _ ->
alloc_cost 1
| Set_iter _ ->
alloc_cost 4
| Set_mem ->
alloc_cost 1
| Set_update ->
alloc_cost 1
| Set_size ->
alloc_cost 1
| Empty_map _ ->
alloc_cost 2
| Map_map _ ->
alloc_cost 5
| Map_iter _ ->
alloc_cost 4
| Map_mem ->
alloc_cost 1
| Map_get ->
alloc_cost 1
| Map_update ->
alloc_cost 1
| Map_size ->
alloc_cost 1
| Empty_big_map _ ->
alloc_cost 2
| Big_map_mem ->
alloc_cost 1
| Big_map_get ->
alloc_cost 1
| Big_map_update ->
alloc_cost 1
| Concat_string ->
alloc_cost 1
| Concat_string_pair ->
alloc_cost 1
| Concat_bytes ->
alloc_cost 1
| Concat_bytes_pair ->
alloc_cost 1
| Slice_string ->
alloc_cost 1
| Slice_bytes ->
alloc_cost 1
| String_size ->
alloc_cost 1
| Bytes_size ->
alloc_cost 1
| Add_seconds_to_timestamp ->
alloc_cost 1
| Add_timestamp_to_seconds ->
alloc_cost 1
| Sub_timestamp_seconds ->
alloc_cost 1
| Diff_timestamps ->
alloc_cost 1
| Add_tez ->
alloc_cost 1
| Sub_tez ->
alloc_cost 1
| Mul_teznat ->
alloc_cost 1
| Mul_nattez ->
alloc_cost 1
| Ediv_teznat ->
alloc_cost 1
| Ediv_tez ->
alloc_cost 1
| Or ->
alloc_cost 1
| And ->
alloc_cost 1
| Xor ->
alloc_cost 1
| Not ->
alloc_cost 1
| Is_nat ->
alloc_cost 1
| Neg_nat ->
alloc_cost 1
| Neg_int ->
alloc_cost 1
| Abs_int ->
alloc_cost 1
| Int_nat ->
alloc_cost 1
| Add_intint ->
alloc_cost 1
| Add_intnat ->
alloc_cost 1
| Add_natint ->
alloc_cost 1
| Add_natnat ->
alloc_cost 1
| Sub_int ->
alloc_cost 1
| Mul_intint ->
alloc_cost 1
| Mul_intnat ->
alloc_cost 1
| Mul_natint ->
alloc_cost 1
| Mul_natnat ->
alloc_cost 1
| Ediv_intint ->
alloc_cost 1
| Ediv_intnat ->
alloc_cost 1
| Ediv_natint ->
alloc_cost 1
| Ediv_natnat ->
alloc_cost 1
| Lsl_nat ->
alloc_cost 1
| Lsr_nat ->
alloc_cost 1
| Or_nat ->
alloc_cost 1
| And_nat ->
alloc_cost 1
| And_int_nat ->
alloc_cost 1
| Xor_nat ->
alloc_cost 1
| Not_nat ->
alloc_cost 1
| Not_int ->
alloc_cost 1
| Seq _ ->
alloc_cost 8
| If _ ->
alloc_cost 8
| Loop _ ->
alloc_cost 4
| Loop_left _ ->
alloc_cost 5
| Dip _ ->
alloc_cost 4
| Exec ->
alloc_cost 1
| Apply _ ->
alloc_cost 1
| Lambda _ ->
alloc_cost 2
| Failwith _ ->
alloc_cost 1
| Nop ->
alloc_cost 0
| Compare _ ->
alloc_cost 1
| Eq ->
alloc_cost 1
| Neq ->
alloc_cost 1
| Lt ->
alloc_cost 1
| Gt ->
alloc_cost 1
| Le ->
alloc_cost 1
| Ge ->
alloc_cost 1
| Address ->
alloc_cost 1
| Contract _ ->
alloc_cost 2
| Transfer_tokens ->
alloc_cost 1
| Create_account ->
alloc_cost 2
| Implicit_account ->
alloc_cost 1
| Create_contract _ ->
alloc_cost 8
(* Deducted the cost of removed arguments manager, spendable and delegatable:
- manager: key_hash = 1
- spendable: bool = 0
- delegatable: bool = 0
*)
| Create_contract_2 _ -> alloc_cost 7
| Set_delegate -> alloc_cost 1
| Now -> alloc_cost 1
| Balance -> alloc_cost 1
| Check_signature -> alloc_cost 1
| Hash_key -> alloc_cost 1
| Pack _ -> alloc_cost 2
| Unpack _ -> alloc_cost 2
| Blake2b -> alloc_cost 1
| Sha256 -> alloc_cost 1
| Sha512 -> alloc_cost 1
| Steps_to_quota -> alloc_cost 1
| Source -> alloc_cost 1
| Sender -> alloc_cost 1
| Self _ -> alloc_cost 2
| Amount -> alloc_cost 1
| Dig (n,_) -> n *@ alloc_cost 1 (* _ is a unary development of n *)
| Dug (n,_) -> n *@ alloc_cost 1
| Dipn (n,_,_) -> n *@ alloc_cost 1
| Dropn (n,_) -> n *@ alloc_cost 1
| ChainId -> alloc_cost 1
| Create_contract_2 _ ->
alloc_cost 7
| Set_delegate ->
alloc_cost 1
| Now ->
alloc_cost 1
| Balance ->
alloc_cost 1
| Check_signature ->
alloc_cost 1
| Hash_key ->
alloc_cost 1
| Pack _ ->
alloc_cost 2
| Unpack _ ->
alloc_cost 2
| Blake2b ->
alloc_cost 1
| Sha256 ->
alloc_cost 1
| Sha512 ->
alloc_cost 1
| Steps_to_quota ->
alloc_cost 1
| Source ->
alloc_cost 1
| Sender ->
alloc_cost 1
| Self _ ->
alloc_cost 2
| Amount ->
alloc_cost 1
| Dig (n, _) ->
n *@ alloc_cost 1 (* _ is a unary development of n *)
| Dug (n, _) ->
n *@ alloc_cost 1
| Dipn (n, _, _) ->
n *@ alloc_cost 1
| Dropn (n, _) ->
n *@ alloc_cost 1
| ChainId ->
alloc_cost 1
end
module Unparse = struct
let prim_cost l annot = Script.prim_node_cost_nonrec_of_length l annot
let seq_cost = Script.seq_node_cost_nonrec_of_length
let string_cost length = Script.string_node_cost_of_length length
let cycle = step_cost 1
let bool = prim_cost 0 []
let unit = prim_cost 0 []
(* We count the length of strings and bytes to prevent hidden
miscalculations due to non detectable expansion of sharing. *)
let string s = Script.string_node_cost s
let bytes s = Script.bytes_node_cost s
let z i = Script.int_node_cost i
let int i = Script.int_node_cost (Script_int.to_zint i)
let tez = Script.int_node_cost_of_numbits 60 (* int64 bound *)
let timestamp x = Script_timestamp.to_zint x |> Script_int.of_zint |> int
let operation bytes = Script.bytes_node_cost bytes
let chain_id bytes = Script.bytes_node_cost bytes
let key = string_cost 54
let key_hash = string_cost 36
let signature = string_cost 128
let contract = string_cost 36
let pair = prim_cost 2 []
let union = prim_cost 1 []
let some = prim_cost 1 []
let none = prim_cost 0 []
let list_element = alloc_cost 2
let set_element = alloc_cost 2
let map_element = alloc_cost 2
let one_arg_type = prim_cost 1
let two_arg_type = prim_cost 2
let set_to_list = Legacy.set_to_list
let map_to_list = Legacy.map_to_list
end
end

View File

@ -26,107 +26,194 @@
open Alpha_context
module Cost_of : sig
val manager_operation : Gas.cost
module Legacy : sig
val z_to_int64 : Gas.cost
val hash : MBytes.t -> int -> Gas.cost
val map_to_list :
('b, 'c) Script_typed_ir.map -> Gas.cost
val map_to_list : ('b, 'c) Script_typed_ir.map -> Gas.cost
val set_update : 'a -> bool -> 'a Script_typed_ir.set -> Gas.cost
end
module Interpreter : sig
val cycle : Gas.cost
val loop_cycle : Gas.cost
val loop_size : Gas.cost
val loop_iter : Gas.cost
val loop_map : Gas.cost
val nop : Gas.cost
val stack_op : Gas.cost
val stack_n_op : int -> Gas.cost
val bool_binop : 'a -> 'b -> Gas.cost
val bool_unop : 'a -> Gas.cost
val pair : Gas.cost
val pair_access : Gas.cost
val cons : Gas.cost
val variant_no_data : Gas.cost
val branch : Gas.cost
val concat_string : string list -> Gas.cost
val concat_bytes : MBytes.t list -> Gas.cost
val slice_string : int -> Gas.cost
val map_mem : 'a -> ('a, 'b) Script_typed_ir.map -> Gas.cost
val map_to_list : ('a, 'b) Script_typed_ir.map -> Gas.cost
val map_get : 'a -> ('a, 'b) Script_typed_ir.map -> Gas.cost
val map_update : 'a -> 'b option -> ('a, 'b) Script_typed_ir.map -> Gas.cost
val map_update :
'a -> 'b option -> ('a, 'b) Script_typed_ir.map -> Gas.cost
val map_size : Gas.cost
val set_to_list : 'a Script_typed_ir.set -> Gas.cost
val set_update : 'a -> bool -> 'a Script_typed_ir.set -> Gas.cost
val set_mem : 'a -> 'a Script_typed_ir.set -> Gas.cost
val mul : 'a Script_int.num -> 'b Script_int.num -> Gas.cost
val div : 'a Script_int.num -> 'b Script_int.num -> Gas.cost
val add : 'a Script_int.num -> 'b Script_int.num -> Gas.cost
val sub : 'a Script_int.num -> 'b Script_int.num -> Gas.cost
val abs : 'a Script_int.num -> Gas.cost
val neg : 'a Script_int.num -> Gas.cost
val int : 'a -> Gas.cost
val add_timestamp : Script_timestamp.t -> 'a Script_int.num -> Gas.cost
val sub_timestamp : Script_timestamp.t -> 'a Script_int.num -> Gas.cost
val diff_timestamps : Script_timestamp.t -> Script_timestamp.t -> Gas.cost
val empty_set : Gas.cost
val set_size : Gas.cost
val empty_map : Gas.cost
val int64_op : Gas.cost
val z_to_int64 : Gas.cost
val int64_to_z : Gas.cost
val logor : 'a Script_int.num -> 'b Script_int.num -> Gas.cost
val logand : 'a Script_int.num -> 'b Script_int.num -> Gas.cost
val logxor : 'a Script_int.num -> 'b Script_int.num -> Gas.cost
val lognot : 'a Script_int.num -> Gas.cost
val shift_left : 'a Script_int.num -> 'b Script_int.num -> Gas.cost
val shift_right : 'a Script_int.num -> 'b Script_int.num -> Gas.cost
val exec : Gas.cost
val push : Gas.cost
val compare_res : Gas.cost
val unpack_failed : MBytes.t -> Gas.cost
val address : Gas.cost
val contract : Gas.cost
val transfer : Gas.cost
val create_account : Gas.cost
val create_contract : Gas.cost
val implicit_account : Gas.cost
val set_delegate : Gas.cost
val balance : Gas.cost
val now : Gas.cost
val check_signature : public_key -> MBytes.t -> Gas.cost
val hash_key : Gas.cost
val hash_blake2b : MBytes.t -> Gas.cost
val hash_sha256 : MBytes.t -> Gas.cost
val hash_sha512 : MBytes.t -> Gas.cost
val steps_to_quota : Gas.cost
val source : Gas.cost
val self : Gas.cost
val amount : Gas.cost
val chain_id : Gas.cost
val wrap : Gas.cost
val compare : 'a Script_typed_ir.comparable_ty -> 'a -> 'a -> Gas.cost
val apply : Gas.cost
end
module Typechecking : sig
val cycle : Gas.cost
val unit : Gas.cost
val bool : Gas.cost
val tez : Gas.cost
val z : Z.t -> Gas.cost
val string : int -> Gas.cost
val bytes : int -> Gas.cost
val int_of_string : string -> Gas.cost
val string_timestamp : Gas.cost
val key : Gas.cost
val key_hash : Gas.cost
val signature : Gas.cost
val chain_id : Gas.cost
val contract : Gas.cost
@ -144,14 +231,19 @@ module Cost_of : sig
val lambda : Gas.cost
val some : Gas.cost
val none : Gas.cost
val list_element : Gas.cost
val set_element : int -> Gas.cost
val map_element : int -> Gas.cost
val primitive_type : Gas.cost
val one_arg_type : Gas.cost
val two_arg_type : Gas.cost
val operation : int -> Gas.cost
@ -165,20 +257,35 @@ module Cost_of : sig
module Unparse : sig
val prim_cost : int -> Script.annot -> Gas.cost
val seq_cost : int -> Gas.cost
val cycle : Gas.cost
val unit : Gas.cost
val bool : Gas.cost
val z : Z.t -> Gas.cost
val int : 'a Script_int.num -> Gas.cost
val tez : Gas.cost
val string : string -> Gas.cost
val bytes : MBytes.t -> Gas.cost
val timestamp : Script_timestamp.t -> Gas.cost
val key : Gas.cost
val key_hash : Gas.cost
val signature : Gas.cost
val operation : MBytes.t -> Gas.cost
val chain_id : MBytes.t -> Gas.cost
val contract : Gas.cost
@ -189,15 +296,21 @@ module Cost_of : sig
val union : Gas.cost
val some : Gas.cost
val none : Gas.cost
val list_element : Gas.cost
val set_element : Gas.cost
val map_element : Gas.cost
val one_arg_type : Script.annot -> Gas.cost
val two_arg_type : Script.annot -> Gas.cost
val set_to_list : 'a Script_typed_ir.set -> Gas.cost
val map_to_list : ('a, 'b) Script_typed_ir.map -> Gas.cost
end
end

View File

@ -26,8 +26,12 @@
open Micheline
type error += Unknown_primitive_name of string
type error += Invalid_case of string
type error += Invalid_primitive_name of string Micheline.canonical * Micheline.canonical_location
type error +=
| Invalid_primitive_name of
string Micheline.canonical * Micheline.canonical_location
type prim =
| K_parameter
@ -153,308 +157,539 @@ let valid_case name =
let is_lower = function '_' | 'a' .. 'z' -> true | _ -> false in
let is_upper = function '_' | 'A' .. 'Z' -> true | _ -> false in
let rec for_all a b f =
Compare.Int.(a > b) || f a && for_all (a + 1) b f in
Compare.Int.(a > b) || (f a && for_all (a + 1) b f)
in
let len = String.length name in
Compare.Int.(len <> 0)
&&
Compare.Char.(String.get name 0 <> '_')
&&
((is_upper (String.get name 0)
&& for_all 1 (len - 1) (fun i -> is_upper (String.get name i)))
||
(is_upper (String.get name 0)
&& for_all 1 (len - 1) (fun i -> is_lower (String.get name i)))
||
(is_lower (String.get name 0)
&& for_all 1 (len - 1) (fun i -> is_lower (String.get name i))))
&& Compare.Char.(name.[0] <> '_')
&& ( (is_upper name.[0] && for_all 1 (len - 1) (fun i -> is_upper name.[i]))
|| (is_upper name.[0] && for_all 1 (len - 1) (fun i -> is_lower name.[i]))
|| (is_lower name.[0] && for_all 1 (len - 1) (fun i -> is_lower name.[i]))
)
let string_of_prim = function
| K_parameter -> "parameter"
| K_storage -> "storage"
| K_code -> "code"
| D_False -> "False"
| D_Elt -> "Elt"
| D_Left -> "Left"
| D_None -> "None"
| D_Pair -> "Pair"
| D_Right -> "Right"
| D_Some -> "Some"
| D_True -> "True"
| D_Unit -> "Unit"
| I_PACK -> "PACK"
| I_UNPACK -> "UNPACK"
| I_BLAKE2B -> "BLAKE2B"
| I_SHA256 -> "SHA256"
| I_SHA512 -> "SHA512"
| I_ABS -> "ABS"
| I_ADD -> "ADD"
| I_AMOUNT -> "AMOUNT"
| I_AND -> "AND"
| I_BALANCE -> "BALANCE"
| I_CAR -> "CAR"
| I_CDR -> "CDR"
| I_CHAIN_ID -> "CHAIN_ID"
| I_CHECK_SIGNATURE -> "CHECK_SIGNATURE"
| I_COMPARE -> "COMPARE"
| I_CONCAT -> "CONCAT"
| I_CONS -> "CONS"
| I_CREATE_ACCOUNT -> "CREATE_ACCOUNT"
| I_CREATE_CONTRACT -> "CREATE_CONTRACT"
| I_IMPLICIT_ACCOUNT -> "IMPLICIT_ACCOUNT"
| I_DIP -> "DIP"
| I_DROP -> "DROP"
| I_DUP -> "DUP"
| I_EDIV -> "EDIV"
| I_EMPTY_BIG_MAP -> "EMPTY_BIG_MAP"
| I_EMPTY_MAP -> "EMPTY_MAP"
| I_EMPTY_SET -> "EMPTY_SET"
| I_EQ -> "EQ"
| I_EXEC -> "EXEC"
| I_APPLY -> "APPLY"
| I_FAILWITH -> "FAILWITH"
| I_GE -> "GE"
| I_GET -> "GET"
| I_GT -> "GT"
| I_HASH_KEY -> "HASH_KEY"
| I_IF -> "IF"
| I_IF_CONS -> "IF_CONS"
| I_IF_LEFT -> "IF_LEFT"
| I_IF_NONE -> "IF_NONE"
| I_INT -> "INT"
| I_LAMBDA -> "LAMBDA"
| I_LE -> "LE"
| I_LEFT -> "LEFT"
| I_LOOP -> "LOOP"
| I_LSL -> "LSL"
| I_LSR -> "LSR"
| I_LT -> "LT"
| I_MAP -> "MAP"
| I_MEM -> "MEM"
| I_MUL -> "MUL"
| I_NEG -> "NEG"
| I_NEQ -> "NEQ"
| I_NIL -> "NIL"
| I_NONE -> "NONE"
| I_NOT -> "NOT"
| I_NOW -> "NOW"
| I_OR -> "OR"
| I_PAIR -> "PAIR"
| I_PUSH -> "PUSH"
| I_RIGHT -> "RIGHT"
| I_SIZE -> "SIZE"
| I_SOME -> "SOME"
| I_SOURCE -> "SOURCE"
| I_SENDER -> "SENDER"
| I_SELF -> "SELF"
| I_SLICE -> "SLICE"
| I_STEPS_TO_QUOTA -> "STEPS_TO_QUOTA"
| I_SUB -> "SUB"
| I_SWAP -> "SWAP"
| I_TRANSFER_TOKENS -> "TRANSFER_TOKENS"
| I_SET_DELEGATE -> "SET_DELEGATE"
| I_UNIT -> "UNIT"
| I_UPDATE -> "UPDATE"
| I_XOR -> "XOR"
| I_ITER -> "ITER"
| I_LOOP_LEFT -> "LOOP_LEFT"
| I_ADDRESS -> "ADDRESS"
| I_CONTRACT -> "CONTRACT"
| I_ISNAT -> "ISNAT"
| I_CAST -> "CAST"
| I_RENAME -> "RENAME"
| I_DIG -> "DIG"
| I_DUG -> "DUG"
| T_bool -> "bool"
| T_contract -> "contract"
| T_int -> "int"
| T_key -> "key"
| T_key_hash -> "key_hash"
| T_lambda -> "lambda"
| T_list -> "list"
| T_map -> "map"
| T_big_map -> "big_map"
| T_nat -> "nat"
| T_option -> "option"
| T_or -> "or"
| T_pair -> "pair"
| T_set -> "set"
| T_signature -> "signature"
| T_string -> "string"
| T_bytes -> "bytes"
| T_mutez -> "mutez"
| T_timestamp -> "timestamp"
| T_unit -> "unit"
| T_operation -> "operation"
| T_address -> "address"
| T_chain_id -> "chain_id"
| K_parameter ->
"parameter"
| K_storage ->
"storage"
| K_code ->
"code"
| D_False ->
"False"
| D_Elt ->
"Elt"
| D_Left ->
"Left"
| D_None ->
"None"
| D_Pair ->
"Pair"
| D_Right ->
"Right"
| D_Some ->
"Some"
| D_True ->
"True"
| D_Unit ->
"Unit"
| I_PACK ->
"PACK"
| I_UNPACK ->
"UNPACK"
| I_BLAKE2B ->
"BLAKE2B"
| I_SHA256 ->
"SHA256"
| I_SHA512 ->
"SHA512"
| I_ABS ->
"ABS"
| I_ADD ->
"ADD"
| I_AMOUNT ->
"AMOUNT"
| I_AND ->
"AND"
| I_BALANCE ->
"BALANCE"
| I_CAR ->
"CAR"
| I_CDR ->
"CDR"
| I_CHAIN_ID ->
"CHAIN_ID"
| I_CHECK_SIGNATURE ->
"CHECK_SIGNATURE"
| I_COMPARE ->
"COMPARE"
| I_CONCAT ->
"CONCAT"
| I_CONS ->
"CONS"
| I_CREATE_ACCOUNT ->
"CREATE_ACCOUNT"
| I_CREATE_CONTRACT ->
"CREATE_CONTRACT"
| I_IMPLICIT_ACCOUNT ->
"IMPLICIT_ACCOUNT"
| I_DIP ->
"DIP"
| I_DROP ->
"DROP"
| I_DUP ->
"DUP"
| I_EDIV ->
"EDIV"
| I_EMPTY_BIG_MAP ->
"EMPTY_BIG_MAP"
| I_EMPTY_MAP ->
"EMPTY_MAP"
| I_EMPTY_SET ->
"EMPTY_SET"
| I_EQ ->
"EQ"
| I_EXEC ->
"EXEC"
| I_APPLY ->
"APPLY"
| I_FAILWITH ->
"FAILWITH"
| I_GE ->
"GE"
| I_GET ->
"GET"
| I_GT ->
"GT"
| I_HASH_KEY ->
"HASH_KEY"
| I_IF ->
"IF"
| I_IF_CONS ->
"IF_CONS"
| I_IF_LEFT ->
"IF_LEFT"
| I_IF_NONE ->
"IF_NONE"
| I_INT ->
"INT"
| I_LAMBDA ->
"LAMBDA"
| I_LE ->
"LE"
| I_LEFT ->
"LEFT"
| I_LOOP ->
"LOOP"
| I_LSL ->
"LSL"
| I_LSR ->
"LSR"
| I_LT ->
"LT"
| I_MAP ->
"MAP"
| I_MEM ->
"MEM"
| I_MUL ->
"MUL"
| I_NEG ->
"NEG"
| I_NEQ ->
"NEQ"
| I_NIL ->
"NIL"
| I_NONE ->
"NONE"
| I_NOT ->
"NOT"
| I_NOW ->
"NOW"
| I_OR ->
"OR"
| I_PAIR ->
"PAIR"
| I_PUSH ->
"PUSH"
| I_RIGHT ->
"RIGHT"
| I_SIZE ->
"SIZE"
| I_SOME ->
"SOME"
| I_SOURCE ->
"SOURCE"
| I_SENDER ->
"SENDER"
| I_SELF ->
"SELF"
| I_SLICE ->
"SLICE"
| I_STEPS_TO_QUOTA ->
"STEPS_TO_QUOTA"
| I_SUB ->
"SUB"
| I_SWAP ->
"SWAP"
| I_TRANSFER_TOKENS ->
"TRANSFER_TOKENS"
| I_SET_DELEGATE ->
"SET_DELEGATE"
| I_UNIT ->
"UNIT"
| I_UPDATE ->
"UPDATE"
| I_XOR ->
"XOR"
| I_ITER ->
"ITER"
| I_LOOP_LEFT ->
"LOOP_LEFT"
| I_ADDRESS ->
"ADDRESS"
| I_CONTRACT ->
"CONTRACT"
| I_ISNAT ->
"ISNAT"
| I_CAST ->
"CAST"
| I_RENAME ->
"RENAME"
| I_DIG ->
"DIG"
| I_DUG ->
"DUG"
| T_bool ->
"bool"
| T_contract ->
"contract"
| T_int ->
"int"
| T_key ->
"key"
| T_key_hash ->
"key_hash"
| T_lambda ->
"lambda"
| T_list ->
"list"
| T_map ->
"map"
| T_big_map ->
"big_map"
| T_nat ->
"nat"
| T_option ->
"option"
| T_or ->
"or"
| T_pair ->
"pair"
| T_set ->
"set"
| T_signature ->
"signature"
| T_string ->
"string"
| T_bytes ->
"bytes"
| T_mutez ->
"mutez"
| T_timestamp ->
"timestamp"
| T_unit ->
"unit"
| T_operation ->
"operation"
| T_address ->
"address"
| T_chain_id ->
"chain_id"
let prim_of_string = function
| "parameter" -> ok K_parameter
| "storage" -> ok K_storage
| "code" -> ok K_code
| "False" -> ok D_False
| "Elt" -> ok D_Elt
| "Left" -> ok D_Left
| "None" -> ok D_None
| "Pair" -> ok D_Pair
| "Right" -> ok D_Right
| "Some" -> ok D_Some
| "True" -> ok D_True
| "Unit" -> ok D_Unit
| "PACK" -> ok I_PACK
| "UNPACK" -> ok I_UNPACK
| "BLAKE2B" -> ok I_BLAKE2B
| "SHA256" -> ok I_SHA256
| "SHA512" -> ok I_SHA512
| "ABS" -> ok I_ABS
| "ADD" -> ok I_ADD
| "AMOUNT" -> ok I_AMOUNT
| "AND" -> ok I_AND
| "BALANCE" -> ok I_BALANCE
| "CAR" -> ok I_CAR
| "CDR" -> ok I_CDR
| "CHAIN_ID" -> ok I_CHAIN_ID
| "CHECK_SIGNATURE" -> ok I_CHECK_SIGNATURE
| "COMPARE" -> ok I_COMPARE
| "CONCAT" -> ok I_CONCAT
| "CONS" -> ok I_CONS
| "CREATE_ACCOUNT" -> ok I_CREATE_ACCOUNT
| "CREATE_CONTRACT" -> ok I_CREATE_CONTRACT
| "IMPLICIT_ACCOUNT" -> ok I_IMPLICIT_ACCOUNT
| "DIP" -> ok I_DIP
| "DROP" -> ok I_DROP
| "DUP" -> ok I_DUP
| "EDIV" -> ok I_EDIV
| "EMPTY_BIG_MAP" -> ok I_EMPTY_BIG_MAP
| "EMPTY_MAP" -> ok I_EMPTY_MAP
| "EMPTY_SET" -> ok I_EMPTY_SET
| "EQ" -> ok I_EQ
| "EXEC" -> ok I_EXEC
| "APPLY" -> ok I_APPLY
| "FAILWITH" -> ok I_FAILWITH
| "GE" -> ok I_GE
| "GET" -> ok I_GET
| "GT" -> ok I_GT
| "HASH_KEY" -> ok I_HASH_KEY
| "IF" -> ok I_IF
| "IF_CONS" -> ok I_IF_CONS
| "IF_LEFT" -> ok I_IF_LEFT
| "IF_NONE" -> ok I_IF_NONE
| "INT" -> ok I_INT
| "LAMBDA" -> ok I_LAMBDA
| "LE" -> ok I_LE
| "LEFT" -> ok I_LEFT
| "LOOP" -> ok I_LOOP
| "LSL" -> ok I_LSL
| "LSR" -> ok I_LSR
| "LT" -> ok I_LT
| "MAP" -> ok I_MAP
| "MEM" -> ok I_MEM
| "MUL" -> ok I_MUL
| "NEG" -> ok I_NEG
| "NEQ" -> ok I_NEQ
| "NIL" -> ok I_NIL
| "NONE" -> ok I_NONE
| "NOT" -> ok I_NOT
| "NOW" -> ok I_NOW
| "OR" -> ok I_OR
| "PAIR" -> ok I_PAIR
| "PUSH" -> ok I_PUSH
| "RIGHT" -> ok I_RIGHT
| "SIZE" -> ok I_SIZE
| "SOME" -> ok I_SOME
| "SOURCE" -> ok I_SOURCE
| "SENDER" -> ok I_SENDER
| "SELF" -> ok I_SELF
| "SLICE" -> ok I_SLICE
| "STEPS_TO_QUOTA" -> ok I_STEPS_TO_QUOTA
| "SUB" -> ok I_SUB
| "SWAP" -> ok I_SWAP
| "TRANSFER_TOKENS" -> ok I_TRANSFER_TOKENS
| "SET_DELEGATE" -> ok I_SET_DELEGATE
| "UNIT" -> ok I_UNIT
| "UPDATE" -> ok I_UPDATE
| "XOR" -> ok I_XOR
| "ITER" -> ok I_ITER
| "LOOP_LEFT" -> ok I_LOOP_LEFT
| "ADDRESS" -> ok I_ADDRESS
| "CONTRACT" -> ok I_CONTRACT
| "ISNAT" -> ok I_ISNAT
| "CAST" -> ok I_CAST
| "RENAME" -> ok I_RENAME
| "DIG" -> ok I_DIG
| "DUG" -> ok I_DUG
| "bool" -> ok T_bool
| "contract" -> ok T_contract
| "int" -> ok T_int
| "key" -> ok T_key
| "key_hash" -> ok T_key_hash
| "lambda" -> ok T_lambda
| "list" -> ok T_list
| "map" -> ok T_map
| "big_map" -> ok T_big_map
| "nat" -> ok T_nat
| "option" -> ok T_option
| "or" -> ok T_or
| "pair" -> ok T_pair
| "set" -> ok T_set
| "signature" -> ok T_signature
| "string" -> ok T_string
| "bytes" -> ok T_bytes
| "mutez" -> ok T_mutez
| "timestamp" -> ok T_timestamp
| "unit" -> ok T_unit
| "operation" -> ok T_operation
| "address" -> ok T_address
| "chain_id" -> ok T_chain_id
| "parameter" ->
ok K_parameter
| "storage" ->
ok K_storage
| "code" ->
ok K_code
| "False" ->
ok D_False
| "Elt" ->
ok D_Elt
| "Left" ->
ok D_Left
| "None" ->
ok D_None
| "Pair" ->
ok D_Pair
| "Right" ->
ok D_Right
| "Some" ->
ok D_Some
| "True" ->
ok D_True
| "Unit" ->
ok D_Unit
| "PACK" ->
ok I_PACK
| "UNPACK" ->
ok I_UNPACK
| "BLAKE2B" ->
ok I_BLAKE2B
| "SHA256" ->
ok I_SHA256
| "SHA512" ->
ok I_SHA512
| "ABS" ->
ok I_ABS
| "ADD" ->
ok I_ADD
| "AMOUNT" ->
ok I_AMOUNT
| "AND" ->
ok I_AND
| "BALANCE" ->
ok I_BALANCE
| "CAR" ->
ok I_CAR
| "CDR" ->
ok I_CDR
| "CHAIN_ID" ->
ok I_CHAIN_ID
| "CHECK_SIGNATURE" ->
ok I_CHECK_SIGNATURE
| "COMPARE" ->
ok I_COMPARE
| "CONCAT" ->
ok I_CONCAT
| "CONS" ->
ok I_CONS
| "CREATE_ACCOUNT" ->
ok I_CREATE_ACCOUNT
| "CREATE_CONTRACT" ->
ok I_CREATE_CONTRACT
| "IMPLICIT_ACCOUNT" ->
ok I_IMPLICIT_ACCOUNT
| "DIP" ->
ok I_DIP
| "DROP" ->
ok I_DROP
| "DUP" ->
ok I_DUP
| "EDIV" ->
ok I_EDIV
| "EMPTY_BIG_MAP" ->
ok I_EMPTY_BIG_MAP
| "EMPTY_MAP" ->
ok I_EMPTY_MAP
| "EMPTY_SET" ->
ok I_EMPTY_SET
| "EQ" ->
ok I_EQ
| "EXEC" ->
ok I_EXEC
| "APPLY" ->
ok I_APPLY
| "FAILWITH" ->
ok I_FAILWITH
| "GE" ->
ok I_GE
| "GET" ->
ok I_GET
| "GT" ->
ok I_GT
| "HASH_KEY" ->
ok I_HASH_KEY
| "IF" ->
ok I_IF
| "IF_CONS" ->
ok I_IF_CONS
| "IF_LEFT" ->
ok I_IF_LEFT
| "IF_NONE" ->
ok I_IF_NONE
| "INT" ->
ok I_INT
| "LAMBDA" ->
ok I_LAMBDA
| "LE" ->
ok I_LE
| "LEFT" ->
ok I_LEFT
| "LOOP" ->
ok I_LOOP
| "LSL" ->
ok I_LSL
| "LSR" ->
ok I_LSR
| "LT" ->
ok I_LT
| "MAP" ->
ok I_MAP
| "MEM" ->
ok I_MEM
| "MUL" ->
ok I_MUL
| "NEG" ->
ok I_NEG
| "NEQ" ->
ok I_NEQ
| "NIL" ->
ok I_NIL
| "NONE" ->
ok I_NONE
| "NOT" ->
ok I_NOT
| "NOW" ->
ok I_NOW
| "OR" ->
ok I_OR
| "PAIR" ->
ok I_PAIR
| "PUSH" ->
ok I_PUSH
| "RIGHT" ->
ok I_RIGHT
| "SIZE" ->
ok I_SIZE
| "SOME" ->
ok I_SOME
| "SOURCE" ->
ok I_SOURCE
| "SENDER" ->
ok I_SENDER
| "SELF" ->
ok I_SELF
| "SLICE" ->
ok I_SLICE
| "STEPS_TO_QUOTA" ->
ok I_STEPS_TO_QUOTA
| "SUB" ->
ok I_SUB
| "SWAP" ->
ok I_SWAP
| "TRANSFER_TOKENS" ->
ok I_TRANSFER_TOKENS
| "SET_DELEGATE" ->
ok I_SET_DELEGATE
| "UNIT" ->
ok I_UNIT
| "UPDATE" ->
ok I_UPDATE
| "XOR" ->
ok I_XOR
| "ITER" ->
ok I_ITER
| "LOOP_LEFT" ->
ok I_LOOP_LEFT
| "ADDRESS" ->
ok I_ADDRESS
| "CONTRACT" ->
ok I_CONTRACT
| "ISNAT" ->
ok I_ISNAT
| "CAST" ->
ok I_CAST
| "RENAME" ->
ok I_RENAME
| "DIG" ->
ok I_DIG
| "DUG" ->
ok I_DUG
| "bool" ->
ok T_bool
| "contract" ->
ok T_contract
| "int" ->
ok T_int
| "key" ->
ok T_key
| "key_hash" ->
ok T_key_hash
| "lambda" ->
ok T_lambda
| "list" ->
ok T_list
| "map" ->
ok T_map
| "big_map" ->
ok T_big_map
| "nat" ->
ok T_nat
| "option" ->
ok T_option
| "or" ->
ok T_or
| "pair" ->
ok T_pair
| "set" ->
ok T_set
| "signature" ->
ok T_signature
| "string" ->
ok T_string
| "bytes" ->
ok T_bytes
| "mutez" ->
ok T_mutez
| "timestamp" ->
ok T_timestamp
| "unit" ->
ok T_unit
| "operation" ->
ok T_operation
| "address" ->
ok T_address
| "chain_id" ->
ok T_chain_id
| n ->
if valid_case n then
error (Unknown_primitive_name n)
else
error (Invalid_case n)
if valid_case n then error (Unknown_primitive_name n)
else error (Invalid_case n)
let prims_of_strings expr =
let rec convert = function
| Int _ | String _ | Bytes _ as expr -> ok expr
| (Int _ | String _ | Bytes _) as expr ->
ok expr
| Prim (loc, prim, args, annot) ->
Error_monad.record_trace
(Invalid_primitive_name (expr, loc))
(prim_of_string prim) >>? fun prim ->
(prim_of_string prim)
>>? fun prim ->
List.fold_left
(fun acc arg ->
acc >>? fun args ->
convert arg >>? fun arg ->
ok (arg :: args))
(ok []) args >>? fun args ->
ok (Prim (0, prim, List.rev args, annot))
acc >>? fun args -> convert arg >>? fun arg -> ok (arg :: args))
(ok [])
args
>>? fun args -> ok (Prim (0, prim, List.rev args, annot))
| Seq (_, args) ->
List.fold_left
(fun acc arg ->
acc >>? fun args ->
convert arg >>? fun arg ->
ok (arg :: args))
(ok []) args >>? fun args ->
ok (Seq (0, List.rev args)) in
convert (root expr) >>? fun expr ->
ok (strip_locations expr)
acc >>? fun args -> convert arg >>? fun arg -> ok (arg :: args))
(ok [])
args
>>? fun args -> ok (Seq (0, List.rev args))
in
convert (root expr) >>? fun expr -> ok (strip_locations expr)
let strings_of_prims expr =
let rec convert = function
| Int _ | String _ | Bytes _ as expr -> expr
| (Int _ | String _ | Bytes _) as expr ->
expr
| Prim (_, prim, args, annot) ->
let prim = string_of_prim prim in
let args = List.map convert args in
Prim (0, prim, args, annot)
| Seq (_, args) ->
let args = List.map convert args in
Seq (0, args) in
Seq (0, args)
in
strip_locations (convert (root expr))
let prim_encoding =
let open Data_encoding in
def "michelson.v1.primitives" @@
string_enum [
(* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *)
def "michelson.v1.primitives"
@@ string_enum
[ (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *)
("parameter", K_parameter);
("storage", K_storage);
("code", K_code);
@ -594,42 +829,36 @@ let () =
`Permanent
~id:"michelson_v1.unknown_primitive_name"
~title:"Unknown primitive name"
~description:
"In a script or data expression, a primitive was unknown."
~description:"In a script or data expression, a primitive was unknown."
~pp:(fun ppf n -> Format.fprintf ppf "Unknown primitive %s." n)
Data_encoding.(obj1 (req "wrong_primitive_name" string))
(function
| Unknown_primitive_name got -> Some got
| _ -> None)
(fun got ->
Unknown_primitive_name got) ;
(function Unknown_primitive_name got -> Some got | _ -> None)
(fun got -> Unknown_primitive_name got) ;
register_error_kind
`Permanent
~id:"michelson_v1.invalid_primitive_name_case"
~title:"Invalid primitive name case"
~description:
"In a script or data expression, a primitive name is \
neither uppercase, lowercase or capitalized."
"In a script or data expression, a primitive name is neither uppercase, \
lowercase or capitalized."
~pp:(fun ppf n -> Format.fprintf ppf "Primitive %s has invalid case." n)
Data_encoding.(obj1 (req "wrong_primitive_name" string))
(function
| Invalid_case name -> Some name
| _ -> None)
(fun name ->
Invalid_case name) ;
(function Invalid_case name -> Some name | _ -> None)
(fun name -> Invalid_case name) ;
register_error_kind
`Permanent
~id:"michelson_v1.invalid_primitive_name"
~title:"Invalid primitive name"
~description:
"In a script or data expression, a primitive name is \
unknown or has a wrong case."
"In a script or data expression, a primitive name is unknown or has a \
wrong case."
~pp:(fun ppf _ -> Format.fprintf ppf "Invalid primitive.")
Data_encoding.(obj2
(req "expression" (Micheline.canonical_encoding ~variant:"generic" string))
Data_encoding.(
obj2
(req
"expression"
(Micheline.canonical_encoding ~variant:"generic" string))
(req "location" Micheline.canonical_location_encoding))
(function
| Invalid_primitive_name (expr, loc) -> Some (expr, loc)
| _ -> None)
(fun (expr, loc) ->
Invalid_primitive_name (expr, loc))
| Invalid_primitive_name (expr, loc) -> Some (expr, loc) | _ -> None)
(fun (expr, loc) -> Invalid_primitive_name (expr, loc))

View File

@ -24,8 +24,14 @@
(*****************************************************************************)
type error += Unknown_primitive_name of string (* `Permanent *)
type error += Invalid_case of string (* `Permanent *)
type error += Invalid_primitive_name of string Micheline.canonical * Micheline.canonical_location (* `Permanent *)
type error +=
| Invalid_primitive_name of
string Micheline.canonical * Micheline.canonical_location
(* `Permanent *)
type prim =
| K_parameter
@ -153,6 +159,7 @@ val string_of_prim : prim -> string
val prim_of_string : string -> prim tzresult
val prims_of_strings : string Micheline.canonical -> prim Micheline.canonical tzresult
val prims_of_strings :
string Micheline.canonical -> prim Micheline.canonical tzresult
val strings_of_prims : prim Micheline.canonical -> string Micheline.canonical

View File

@ -24,61 +24,56 @@
(*****************************************************************************)
type 'a lazyt = unit -> 'a
type 'a lazy_list_t = LCons of 'a * ('a lazy_list_t tzresult Lwt.t lazyt)
type 'a lazy_list_t = LCons of 'a * 'a lazy_list_t tzresult Lwt.t lazyt
type 'a lazy_list = 'a lazy_list_t tzresult Lwt.t
let rec (-->) i j = (* [i; i+1; ...; j] *)
if Compare.Int.(i > j)
then []
else i :: (succ i --> j)
let rec ( --> ) i j =
(* [i; i+1; ...; j] *)
if Compare.Int.(i > j) then [] else i :: (succ i --> j)
let rec (--->) i j = (* [i; i+1; ...; j] *)
if Compare.Int32.(i > j)
then []
else i :: (Int32.succ i ---> j)
let rec ( ---> ) i j =
(* [i; i+1; ...; j] *)
if Compare.Int32.(i > j) then [] else i :: (Int32.succ i ---> j)
let split delim ?(limit = max_int) path =
let l = String.length path in
let rec do_slashes acc limit i =
if Compare.Int.(i >= l) then
List.rev acc
else if Compare.Char.(String.get path i = delim) then
do_slashes acc limit (i + 1)
else
do_split acc limit i
if Compare.Int.(i >= l) then List.rev acc
else if Compare.Char.(path.[i] = delim) then do_slashes acc limit (i + 1)
else do_split acc limit i
and do_split acc limit i =
if Compare.Int.(limit <= 0) then
if Compare.Int.(i = l) then
List.rev acc
else
List.rev (String.sub path i (l - i) :: acc)
else
do_component acc (pred limit) i i
if Compare.Int.(i = l) then List.rev acc
else List.rev (String.sub path i (l - i) :: acc)
else do_component acc (pred limit) i i
and do_component acc limit i j =
if Compare.Int.(j >= l) then
if Compare.Int.(i = j) then
List.rev acc
else
List.rev (String.sub path i (j - i) :: acc)
else if Compare.Char.(String.get path j = delim) then
if Compare.Int.(i = j) then List.rev acc
else List.rev (String.sub path i (j - i) :: acc)
else if Compare.Char.(path.[j] = delim) then
do_slashes (String.sub path i (j - i) :: acc) limit j
else
do_component acc limit i (j + 1) in
if Compare.Int.(limit > 0) then
do_slashes [] limit 0
else
[ path ]
else do_component acc limit i (j + 1)
in
if Compare.Int.(limit > 0) then do_slashes [] limit 0 else [path]
let pp_print_paragraph ppf description =
Format.fprintf ppf "@[%a@]"
Format.fprintf
ppf
"@[%a@]"
Format.(pp_print_list ~pp_sep:pp_print_space pp_print_string)
(split ' ' description)
let take n l =
let rec loop acc n = function
| xs when Compare.Int.(n <= 0) -> Some (List.rev acc, xs)
| [] -> None
| x :: xs -> loop (x :: acc) (n-1) xs in
| xs when Compare.Int.(n <= 0) ->
Some (List.rev acc, xs)
| [] ->
None
| x :: xs ->
loop (x :: acc) (n - 1) xs
in
loop [] n l
let remove_prefix ~prefix s =
@ -86,10 +81,12 @@ let remove_prefix ~prefix s =
let n = String.length s in
if Compare.Int.(n >= x) && Compare.String.(String.sub s 0 x = prefix) then
Some (String.sub s x (n - x))
else
None
else None
let rec remove_elem_from_list nb = function
| [] -> []
| l when Compare.Int.(nb <= 0) -> l
| _ :: tl -> remove_elem_from_list (nb - 1) tl
| [] ->
[]
| l when Compare.Int.(nb <= 0) ->
l
| _ :: tl ->
remove_elem_from_list (nb - 1) tl

View File

@ -26,18 +26,21 @@
(** {2 Helper functions} *)
type 'a lazyt = unit -> 'a
type 'a lazy_list_t = LCons of 'a * ('a lazy_list_t tzresult Lwt.t lazyt)
type 'a lazy_list_t = LCons of 'a * 'a lazy_list_t tzresult Lwt.t lazyt
type 'a lazy_list = 'a lazy_list_t tzresult Lwt.t
(** Include bounds *)
val ( --> ) : int -> int -> int list
val ( ---> ) : Int32.t -> Int32.t -> Int32.t list
val pp_print_paragraph : Format.formatter -> string -> unit
val take : int -> 'a list -> ('a list * 'a list) option
(** Some (input with [prefix] removed), if string has [prefix], else [None] **)
(** Some (input with [prefix] removed), if string has [prefix], else [None] *)
val remove_prefix : prefix:string -> string -> string option
(** [remove nb list] remove the first [nb] elements from the list [list]. *)

Some files were not shown because too many files have changed in this diff Show More