diff --git a/compiler.go b/compiler.go index 51ed17e..9452a98 100644 --- a/compiler.go +++ b/compiler.go @@ -17,8 +17,8 @@ type rawCompilerOutput struct { Contracts map[string]contract.RawCompiledContract } -func (o *rawCompilerOutput) CompiledContracts() map[string]contract.CompiledContract { - contracts := make(map[string]contract.CompiledContract) +func (o *rawCompilerOutput) CompiledContracts() contract.CompiledContracts { + contracts := make(contract.CompiledContracts) for name, rawContract := range o.Contracts { if len(rawContract.Bin) == 0 { @@ -32,14 +32,15 @@ func (o *rawCompilerOutput) CompiledContracts() map[string]contract.CompiledCont contractName = parts[1] } - compiledContract := contract.CompiledContract{ + compiledContract := &contract.CompiledContract{ + Source: name, Name: contractName, Bin: rawContract.Bin, BinKeccak256: rawContract.BinHash256(), ABI: rawContract.Metadata.Output.ABI, } - contracts[contractName] = compiledContract + contracts[name] = compiledContract } return contracts @@ -64,27 +65,59 @@ type Compiler struct { Filename string Opts CompilerOptions Repo *contract.ContractsRepository + + compiledContracts contract.CompiledContracts +} + +func (c *Compiler) mainContractSource() string { + mainContractName := basenameNoExt(c.Filename) + + return c.Filename + ":" + mainContractName +} + +func (c *Compiler) mainContractName() string { + mainContractName := basenameNoExt(c.Filename) + return mainContractName } // Compile returns only the contract that has the same name as the source file func (c *Compiler) Compile() (*contract.CompiledContract, error) { - mainContractName := basenameNoExt(c.Filename) - contracts, err := c.CompileAll() + contracts, err := c.getCompiledContracts() if err != nil { return nil, err } - contract, ok := contracts[mainContractName] + contractSrc := c.mainContractSource() + contract, ok := contracts[contractSrc] if !ok { - return nil, errors.Errorf("cannot find contract: %s", mainContractName) + return nil, errors.Errorf("cannot find contract: %s", c.mainContractName()) + } + + return contract, nil +} + +func (c *Compiler) RelatedContracts() (contract.CompiledContracts, error) { + contracts, err := c.getCompiledContracts() + if err != nil { + return nil, err } - return &contract, nil + contractSrc := c.mainContractSource() + relatedContracts := make(contract.CompiledContracts) + for name, contract := range contracts { + if name == contractSrc { + continue + } + + relatedContracts[name] = contract + } + + return relatedContracts, nil } // CompileAll returns all contracts in a source file -func (c *Compiler) CompileAll() (map[string]contract.CompiledContract, error) { +func (c *Compiler) compileAll() (contract.CompiledContracts, error) { _, err := os.Stat(c.Filename) if err != nil && os.IsNotExist(err) { @@ -99,6 +132,20 @@ func (c *Compiler) CompileAll() (map[string]contract.CompiledContract, error) { return output.CompiledContracts(), nil } +func (c *Compiler) getCompiledContracts() (contract.CompiledContracts, error) { + if c.compiledContracts != nil { + return c.compiledContracts, nil + } + + contracts, err := c.compileAll() + if err != nil { + return nil, err + } + + c.compiledContracts = contracts + return contracts, nil +} + func (c *Compiler) execSolc() (*rawCompilerOutput, error) { opts := c.Opts diff --git a/contract/compiledContract.go b/contract/compiledContract.go index 340bc76..af70ce9 100644 --- a/contract/compiledContract.go +++ b/contract/compiledContract.go @@ -31,9 +31,11 @@ type ABIType struct { } type CompiledContract struct { - Name string `json:"name"` - ABI []ABIDefinition `json:"abi"` - Bin Bytes `json:"bin"` + // Where the contract is defined + Source string `json:"source"` + Name string `json:"name"` + ABI []ABIDefinition `json:"abi"` + Bin Bytes `json:"bin"` // KECAAK256 of bytecode without auxdata BinKeccak256 Bytes `json:"binhash"` } diff --git a/contract/contractsRepo.go b/contract/contractsRepo.go index c3af913..b91e3c1 100644 --- a/contract/contractsRepo.go +++ b/contract/contractsRepo.go @@ -10,6 +10,8 @@ import ( "github.com/pkg/errors" ) +type CompiledContracts map[string]*CompiledContract + type DeployedContracts map[string]*DeployedContract type DeployedContract struct { @@ -30,6 +32,9 @@ type ContractsRepository struct { filepath string Contracts DeployedContracts `json:"contracts"` Libraries DeployedContracts `json:"libraries"` + + // ABI definitions related to the contracts, but not deployed. + Related CompiledContracts `json:"related"` } func OpenContractsRepository(filepath string) (repo *ContractsRepository, err error) { @@ -39,6 +44,7 @@ func OpenContractsRepository(filepath string) (repo *ContractsRepository, err er filepath: filepath, Contracts: make(DeployedContracts), Libraries: make(DeployedContracts), + Related: make(CompiledContracts), }, nil } @@ -65,6 +71,10 @@ func OpenContractsRepository(filepath string) (repo *ContractsRepository, err er repo.Contracts = make(DeployedContracts) } + if repo.Related == nil { + repo.Related = make(CompiledContracts) + } + return } diff --git a/deploy.go b/deploy.go index f88f948..d03307e 100644 --- a/deploy.go +++ b/deploy.go @@ -1,11 +1,12 @@ package solar import ( - "github.com/qtumproject/solar/contract" "fmt" "log" "strings" + "github.com/qtumproject/solar/contract" + "github.com/pkg/errors" ) @@ -80,6 +81,23 @@ func init() { return } + // Add related contracts to repo + relatedContracts, err := compiler.RelatedContracts() + if err != nil { + return err + } + + if len(relatedContracts) > 0 { + for name, c := range relatedContracts { + repo.Related[name] = c + } + + err = repo.Commit() + if err != nil { + return + } + } + newContracts := repo.UnconfirmedContracts() if *noconfirm == false && len(newContracts) != 0 { // Force local chain to generate a block immediately. diff --git a/deployer/qtum/qtumDeployer.go b/deployer/qtum/qtumDeployer.go index 9173bb0..8a4a3ec 100644 --- a/deployer/qtum/qtumDeployer.go +++ b/deployer/qtum/qtumDeployer.go @@ -26,7 +26,7 @@ func NewDeployer(rpcURL *url.URL, repo *contract.ContractsRepository, senderAddr BaseURL: rpcURL, }, ContractsRepository: repo, - senderAddress: senderAddress, + senderAddress: senderAddress, }, nil } @@ -80,7 +80,7 @@ func (d *Deployer) CreateContract(c *contract.CompiledContract, jsonParams []byt args = append(args, d.senderAddress) } - err = d.rpc.Call(&tx,"createcontract", args...) + err = d.rpc.Call(&tx, "createcontract", args...) if err != nil { return errors.Wrap(err, "createcontract")