Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 26 additions & 10 deletions contract/AElf.Contracts.Genesis/BasicContractZero.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,15 @@ public override Address DeploySystemSmartContract(SystemContractDeploymentInput
var code = input.Code.ToByteArray();
var transactionMethodCallList = input.TransactionMethodCallList;

if (name != null)
Assert(State.NameAddressMapping[name] == null, "contract name has already been registered before");
// Context.Sender should be identical to Genesis contract address before initialization in production
var address = DeploySmartContract(name, category, code, true, Context.Sender, false);
var reg = Extensions.CreateNewSmartContractRegistration(category, code).SetIsSystemContract(true);
AssertContractNotExists(reg.CodeHash);
var address = DeploySmartContractInternal(reg, Context.Sender, name);

if (name != null)
State.NameAddressMapping[name] = address;

if (transactionMethodCallList != null)
foreach (var methodCall in transactionMethodCallList.Value)
Expand All @@ -126,10 +133,10 @@ public override Hash ProposeNewContract(ContractDeploymentInput input)
if (input.ContractOperation != null)
{
ValidateContractOperation(input.ContractOperation, 0, codeHash);

// Remove one time signer if exists. Signer is only needed for validating signature.
RemoveOneTimeSigner(input.ContractOperation.Deployer);

AssertContractAddressAvailable(input.ContractOperation.Deployer, input.ContractOperation.Salt);
}

Expand Down Expand Up @@ -308,11 +315,16 @@ public override Address DeploySmartContract(ContractDeploymentInput input)
var inputHash = CalculateHashFromInput(input);
TryClearContractProposingData(inputHash, out var contractProposingInput);

var address =
DeploySmartContract(null, input.Category, input.Code.ToByteArray(), false,
DecideNonSystemContractAuthor(contractProposingInput?.Proposer, Context.Sender), false,
input.ContractOperation?.Deployer, input.ContractOperation?.Salt);
return address;
var reg = Extensions.CreateNewSmartContractRegistration(input.Category, input.Code.ToByteArray());
AssertContractNotExists(reg.CodeHash);
var author = DecideNonSystemContractAuthor(contractProposingInput?.Proposer, Context.Sender);
if (input.RequiresDeterministicAddress())
{
return DeploySmartContractInternal(reg, author, input.ContractOperation.Deployer,
input.ContractOperation.Salt);
}

return DeploySmartContractInternal(reg, author);
}

public override Address UpdateSmartContract(ContractUpdateInput input)
Expand Down Expand Up @@ -484,8 +496,12 @@ public override Address PerformDeployUserSmartContract(UserContractDeploymentInp
var inputHash = CalculateHashFromInput(input);
TryClearContractProposingData(inputHash, out var contractProposingInput);

var address = DeploySmartContract(null, input.Category, input.Code.ToByteArray(), false,
contractProposingInput.Author, true, contractProposingInput.Author, input.Salt);
var reg = Extensions.CreateNewSmartContractRegistration(input.Category, input.Code.ToByteArray())
.SetIsUserContract(true);
var author = contractProposingInput.Author;
var deployer = contractProposingInput.Author;
var salt = input.Salt;
var address = DeploySmartContractInternal(reg, author, deployer, salt);
return address;
}

Expand Down
101 changes: 33 additions & 68 deletions contract/AElf.Contracts.Genesis/BasicContractZero_Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,85 +12,50 @@ namespace AElf.Contracts.Genesis;

public partial class BasicContractZero
{
private Address DeploySmartContract(Hash name, int category, byte[] code, bool isSystemContract,
Address author, bool isUserContract, Address deployer = null, Hash salt = null)
private void AddCodeHashToList(Hash codeHash)
{
if (name != null)
Assert(State.NameAddressMapping[name] == null, "contract name has already been registered before");

var codeHash = HashHelper.ComputeFrom(code);
AssertContractNotExists(codeHash);

long serialNumber;
Address contractAddress;
var contractCodeHashList =
State.ContractCodeHashListMap[Context.CurrentHeight] ?? new ContractCodeHashList();
contractCodeHashList.Value.Add(codeHash);
State.ContractCodeHashListMap[Context.CurrentHeight] = contractCodeHashList;
}

if (salt == null)
{
serialNumber = State.ContractSerialNumber.Value;
// Increment
State.ContractSerialNumber.Value = serialNumber + 1;
contractAddress = AddressHelper.ComputeContractAddress(Context.ChainId, serialNumber);
}
else
{
serialNumber = 0;
contractAddress = AddressHelper.ComputeContractAddress(deployer, salt);
}
private ContractDeployed DeploySmartContractInternalCore(SmartContractRegistration reg, Address author,
Address contractAddress, long serialNumber, Hash name = null)
{
AssertContractNotExists(reg.CodeHash);

Assert(State.ContractInfos[contractAddress] == null, "Contract address exists.");

var info = new ContractInfo
{
SerialNumber = serialNumber,
Author = author,
Category = category,
CodeHash = codeHash,
IsSystemContract = isSystemContract,
Version = 1,
IsUserContract = isUserContract,
Deployer = deployer
};

var reg = new SmartContractRegistration
{
Category = category,
Code = ByteString.CopyFrom(code),
CodeHash = codeHash,
IsSystemContract = info.IsSystemContract,
Version = info.Version,
ContractAddress = contractAddress,
IsUserContract = isUserContract
};

var contractInfo = Context.DeploySmartContract(contractAddress, reg, name);

info.ContractVersion = contractInfo.ContractVersion;
reg.ContractVersion = info.ContractVersion;
State.ContractInfos[contractAddress] = Extensions.CreateContractInfo(reg, author)
.SetSerialNumber(serialNumber)
.SetContractVersion(contractInfo.ContractVersion);
State.SmartContractRegistrations[reg.CodeHash] = reg.SetContractVersion(contractInfo.ContractVersion);
AddCodeHashToList(reg.CodeHash);

State.ContractInfos[contractAddress] = info;
State.SmartContractRegistrations[reg.CodeHash] = reg;
Context.LogDebug(() => "BasicContractZero - Deployment ContractHash: " + reg.CodeHash.ToHex());
Context.LogDebug(() => "BasicContractZero - Deployment success: " + contractAddress.ToBase58());
return Extensions.CreateContractDeployedEvent(reg, contractAddress).SetAuthor(author).SetName(name);
}

Context.Fire(new ContractDeployed
{
CodeHash = codeHash,
Address = contractAddress,
Author = author,
Version = info.Version,
Name = name,
ContractVersion = info.ContractVersion,
Deployer = deployer
});
private Address DeploySmartContractInternal(SmartContractRegistration reg, Address author, Hash name = null)
{
var serialNumber = State.ContractSerialNumber.Value;
// Increment
State.ContractSerialNumber.Value = serialNumber + 1;
var contractAddress = AddressHelper.ComputeContractAddress(Context.ChainId, serialNumber);

Context.LogDebug(() => "BasicContractZero - Deployment ContractHash: " + codeHash.ToHex());
Context.LogDebug(() => "BasicContractZero - Deployment success: " + contractAddress.ToBase58());
Context.Fire(DeploySmartContractInternalCore(reg, author, contractAddress, serialNumber, name));

if (name != null)
State.NameAddressMapping[name] = contractAddress;
return contractAddress;
}

var contractCodeHashList =
State.ContractCodeHashListMap[Context.CurrentHeight] ?? new ContractCodeHashList();
contractCodeHashList.Value.Add(codeHash);
State.ContractCodeHashListMap[Context.CurrentHeight] = contractCodeHashList;
private Address DeploySmartContractInternal(SmartContractRegistration reg, Address author, Address deployer,
Hash salt)
{
var contractAddress = AddressHelper.ComputeContractAddress(deployer, salt);
Context.Fire(DeploySmartContractInternalCore(reg, author, contractAddress, 0, null));

return contractAddress;
}
Expand Down
116 changes: 116 additions & 0 deletions contract/AElf.Contracts.Genesis/Extensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
using AElf.Standards.ACS0;
using AElf.Types;
using Google.Protobuf;

namespace AElf.Contracts.Genesis
{
public static class Extensions
{
public static SmartContractRegistration CreateNewSmartContractRegistration(int category, byte[] code)
{
var codeHash = HashHelper.ComputeFrom(code);
return new SmartContractRegistration
{
Category = category,
Code = ByteString.CopyFrom(code),
CodeHash = codeHash
};
}

public static SmartContractRegistration SetIsUserContract(this SmartContractRegistration self,
bool isUserContract)
{
self.IsSystemContract = isUserContract;
return self;
}

public static SmartContractRegistration SetVersion(this SmartContractRegistration self, int version)
{
self.Version = version;
return self;
}

public static SmartContractRegistration SetContractVersion(this SmartContractRegistration self,
string contractVersion)
{
self.ContractVersion = contractVersion;
return self;
}

public static SmartContractRegistration SetIsSystemContract(this SmartContractRegistration self,
bool isSystemContract)
{
self.IsSystemContract = isSystemContract;
return self;
}

public static ContractInfo CreateContractInfo(SmartContractRegistration reg, Address author)
{
return new ContractInfo
{
Author = author,
Category = reg.Category,
CodeHash = reg.CodeHash,
IsSystemContract = reg.IsSystemContract,
Version = reg.Version,
IsUserContract = reg.IsUserContract
};
}

public static ContractInfo SetSerialNumber(this ContractInfo self, long serialNumber)
{
self.SerialNumber = serialNumber;
return self;
}

public static ContractInfo SetContractVersion(this ContractInfo self, string contractVersion)
{
self.ContractVersion = contractVersion;
return self;
}

public static ContractDeployed CreateContractDeployedEvent(SmartContractRegistration reg, Address contractAddress)
{
return new ContractDeployed
{
CodeHash = reg.CodeHash,
Version = reg.Version,
Address = contractAddress,
ContractVersion = reg.ContractVersion
};
}

public static ContractDeployed SetAuthor(this ContractDeployed self, Address author)
{
self.Author = author;
return self;
}

public static ContractDeployed SetDeployer(this ContractDeployed self, Address deployer)
{
self.Deployer = deployer;
return self;
}

public static ContractDeployed SetName(this ContractDeployed self, Hash name)
{
self.Name = name;
return self;
}

public static bool RequiresDeterministicAddress(this ContractDeploymentInput self)
{
if (self.ContractOperation == null)
{
return false;
}

if (self.ContractOperation.Salt == null)
{
return false;
}

return self.ContractOperation.Deployer != null;
}
}
}