mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Move state model filtering from CHC to Predicate
This commit is contained in:
parent
e3a8c94ace
commit
2e2e96cc93
@ -1429,6 +1429,8 @@ optional<string> CHC::generateCounterexample(CHCSolverInterface::CexGraph const&
|
|||||||
solAssert((calledFun && !calledContract) || (!calledFun && calledContract), "");
|
solAssert((calledFun && !calledContract) || (!calledFun && calledContract), "");
|
||||||
auto stateVars = summaryPredicate->stateVariables();
|
auto stateVars = summaryPredicate->stateVariables();
|
||||||
solAssert(stateVars.has_value(), "");
|
solAssert(stateVars.has_value(), "");
|
||||||
|
auto stateValues = summaryPredicate->summaryStateValues(summaryNode.second);
|
||||||
|
solAssert(stateValues.size() == stateVars->size(), "");
|
||||||
|
|
||||||
/// This summary node is the end of a tx.
|
/// This summary node is the end of a tx.
|
||||||
/// If it is the first summary node seen in this loop, it is the summary
|
/// If it is the first summary node seen in this loop, it is the summary
|
||||||
@ -1438,7 +1440,7 @@ optional<string> CHC::generateCounterexample(CHCSolverInterface::CexGraph const&
|
|||||||
{
|
{
|
||||||
lastTxSeen = true;
|
lastTxSeen = true;
|
||||||
/// Generate counterexample message local to the failed target.
|
/// Generate counterexample message local to the failed target.
|
||||||
localState = formatStateCounterexample(*stateVars, calledFun, summaryNode.second) + "\n";
|
localState = formatStateCounterexample(*stateVars, stateValues) + "\n";
|
||||||
if (calledFun)
|
if (calledFun)
|
||||||
{
|
{
|
||||||
/// The signature of a summary predicate is: summary(error, preStateVars, preInputVars, postInputVars, outputVars).
|
/// The signature of a summary predicate is: summary(error, preStateVars, preInputVars, postInputVars, outputVars).
|
||||||
@ -1465,7 +1467,7 @@ optional<string> CHC::generateCounterexample(CHCSolverInterface::CexGraph const&
|
|||||||
else
|
else
|
||||||
/// We report the state after every tx in the trace except for the last, which is reported
|
/// We report the state after every tx in the trace except for the last, which is reported
|
||||||
/// first in the code above.
|
/// first in the code above.
|
||||||
path.emplace_back("State: " + formatStateCounterexample(*stateVars, calledFun, summaryNode.second));
|
path.emplace_back("State: " + formatStateCounterexample(*stateVars, stateValues));
|
||||||
|
|
||||||
string txCex = summaryPredicate->formatSummaryCall(summaryNode.second);
|
string txCex = summaryPredicate->formatSummaryCall(summaryNode.second);
|
||||||
path.emplace_back(txCex);
|
path.emplace_back(txCex);
|
||||||
@ -1481,35 +1483,16 @@ optional<string> CHC::generateCounterexample(CHCSolverInterface::CexGraph const&
|
|||||||
return localState + "\nTransaction trace:\n" + boost::algorithm::join(boost::adaptors::reverse(path), "\n");
|
return localState + "\nTransaction trace:\n" + boost::algorithm::join(boost::adaptors::reverse(path), "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
string CHC::formatStateCounterexample(vector<VariableDeclaration const*> const& _stateVars, FunctionDefinition const* _function, vector<string> const& _summaryValues)
|
string CHC::formatStateCounterexample(vector<VariableDeclaration const*> const& _stateVars, vector<string> const& _values)
|
||||||
{
|
{
|
||||||
/// The signature of a function summary predicate is: summary(error, preStateVars, preInputVars, postInputVars, outputVars).
|
solAssert(_stateVars.size() == _values.size(), "");
|
||||||
/// The signature of an implicit constructor summary predicate is: summary(error, postStateVars).
|
|
||||||
/// Here we are interested in postStateVars.
|
|
||||||
vector<string>::const_iterator stateFirst;
|
|
||||||
vector<string>::const_iterator stateLast;
|
|
||||||
if (_function)
|
|
||||||
{
|
|
||||||
stateFirst = _summaryValues.begin() + 1 + static_cast<int>(_stateVars.size()) + static_cast<int>(_function->parameters().size());
|
|
||||||
stateLast = stateFirst + static_cast<int>(_stateVars.size());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stateFirst = _summaryValues.begin() + 1;
|
|
||||||
stateLast = stateFirst + static_cast<int>(_stateVars.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
solAssert(stateFirst >= _summaryValues.begin() && stateFirst <= _summaryValues.end(), "");
|
|
||||||
solAssert(stateLast >= _summaryValues.begin() && stateLast <= _summaryValues.end(), "");
|
|
||||||
vector<string> stateArgs(stateFirst, stateLast);
|
|
||||||
solAssert(stateArgs.size() == _stateVars.size(), "");
|
|
||||||
|
|
||||||
vector<string> stateCex;
|
vector<string> stateCex;
|
||||||
for (unsigned i = 0; i < stateArgs.size(); ++i)
|
for (unsigned i = 0; i < _values.size(); ++i)
|
||||||
{
|
{
|
||||||
auto var = _stateVars.at(i);
|
auto var = _stateVars.at(i);
|
||||||
if (var->type()->isValueType())
|
if (var->type()->isValueType())
|
||||||
stateCex.emplace_back(var->name() + " = " + stateArgs.at(i));
|
stateCex.emplace_back(var->name() + " = " + _values.at(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
return boost::algorithm::join(stateCex, ", ");
|
return boost::algorithm::join(stateCex, ", ");
|
||||||
|
@ -225,7 +225,7 @@ private:
|
|||||||
/// _function was executed.
|
/// _function was executed.
|
||||||
/// _function = nullptr means the transaction was the deployment of a
|
/// _function = nullptr means the transaction was the deployment of a
|
||||||
/// contract without an explicit constructor.
|
/// contract without an explicit constructor.
|
||||||
std::string formatStateCounterexample(std::vector<VariableDeclaration const*> const& _stateVariables, FunctionDefinition const* _function, std::vector<std::string> const& _summaryValues);
|
std::string formatStateCounterexample(std::vector<VariableDeclaration const*> const& _stateVariables, std::vector<std::string> const& _values);
|
||||||
|
|
||||||
/// @returns a DAG in the dot format.
|
/// @returns a DAG in the dot format.
|
||||||
/// Used for debugging purposes.
|
/// Used for debugging purposes.
|
||||||
|
@ -182,3 +182,35 @@ string Predicate::formatSummaryCall(vector<string> const& _args) const
|
|||||||
return fName + "(" + boost::algorithm::join(functionArgs, ", ") + ")";
|
return fName + "(" + boost::algorithm::join(functionArgs, ", ") + ")";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<string> Predicate::summaryStateValues(vector<string> const& _args) const
|
||||||
|
{
|
||||||
|
/// The signature of a function summary predicate is: summary(error, preStateVars, preInputVars, postStateVars, postInputVars, outputVars).
|
||||||
|
/// The signature of an implicit constructor summary predicate is: summary(error, postStateVars).
|
||||||
|
/// Here we are interested in postStateVars.
|
||||||
|
|
||||||
|
auto stateVars = stateVariables();
|
||||||
|
solAssert(stateVars.has_value(), "");
|
||||||
|
|
||||||
|
vector<string>::const_iterator stateFirst;
|
||||||
|
vector<string>::const_iterator stateLast;
|
||||||
|
if (auto const* function = programFunction())
|
||||||
|
{
|
||||||
|
stateFirst = _args.begin() + 1 + static_cast<int>(stateVars->size()) + static_cast<int>(function->parameters().size());
|
||||||
|
stateLast = stateFirst + static_cast<int>(stateVars->size());
|
||||||
|
}
|
||||||
|
else if (programContract())
|
||||||
|
{
|
||||||
|
stateFirst = _args.begin() + 1;
|
||||||
|
stateLast = stateFirst + static_cast<int>(stateVars->size());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
solAssert(false, "");
|
||||||
|
|
||||||
|
solAssert(stateFirst >= _args.begin() && stateFirst <= _args.end(), "");
|
||||||
|
solAssert(stateLast >= _args.begin() && stateLast <= _args.end(), "");
|
||||||
|
|
||||||
|
vector<string> stateArgs(stateFirst, stateLast);
|
||||||
|
solAssert(stateArgs.size() == stateVars->size(), "");
|
||||||
|
return stateArgs;
|
||||||
|
}
|
||||||
|
@ -92,6 +92,10 @@ public:
|
|||||||
/// with _args.
|
/// with _args.
|
||||||
std::string formatSummaryCall(std::vector<std::string> const& _args) const;
|
std::string formatSummaryCall(std::vector<std::string> const& _args) const;
|
||||||
|
|
||||||
|
/// @returns the values of the state variables from _args at the point
|
||||||
|
/// where this summary was reached.
|
||||||
|
std::vector<std::string> summaryStateValues(std::vector<std::string> const& _args) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// The actual SMT expression.
|
/// The actual SMT expression.
|
||||||
smt::SymbolicFunctionVariable m_predicate;
|
smt::SymbolicFunctionVariable m_predicate;
|
||||||
|
Loading…
Reference in New Issue
Block a user